iOS/Objective-C

[Objective-C] Objective-C에서의 메모리 관리

TDCIAN 2023. 4. 12. 10:33

 

 

Q. Objective-C로 iOS 애플리케이션을 개발하는 과정에서 ARC가 적용된 시기는 iOS 버전 몇 때부터인지 알려줘

 

A. Objective-C에서 ARC(자동 참조 계산)는 iOS 5 이상에서 지원됩니다. 

이전 버전의 iOS에서는 수동으로 메모리 관리를 해야 했습니다.

따라서 iOS 5 이전 버전에서 개발할 경우에는 수동으로 메모리를 관리해야 합니다.

 

Q. 수동으로 메모리를 관리하는 Objective-C 코드를 보여줘

 

A. Objective-C에서 수동으로 메모리를 관리하기 위해서는 메모리를 할당할 때 'alloc' 메소드를 사용하고, 메모리를 해제할 때 'release' 메소드를 호출해야 합니다. 또한, 객체를 참조할 때는 'retain' 메소드를 사용해서 참조 횟수를 증가시키고, 참조를 해제할 때는 'release' 메소드를 사용해서 참조 횟수를 감소시켜야 합니다.

 

아래는 예시 코드입니다.

// 객체 생성 및 초기화
NSString *myString = [[NSString alloc] initWithString:@"Hello, World!"];

// 객체 참조 카운트 증가
[myString retain];

// 객체 사용
NSLog(@"%@", myString);

// 객체 참조 카운트 감소
[myString release];

// 객체 소멸
[myString dealloc];

위 코드에서 'alloc' 메소드로 'NSString' 객체를 생성하고, 'retain' 메소드로 참조 횟수를 증가시킨 후, 'NSLog' 함수를 사용해서 객체를 사용합니다. 마지막으로 'release' 메소드로 참조 횟수를 감소시키고, 'dealloc' 메소드로 객체를 해제합니다. 이와 같은 방식으로 수동으로 메모리를 관리해야 합니다.

 

Q. 그럼 이번에는 iOS 5 이후부터 가능해진 ARC를 활용한 메모리 관리 방법에 대해 설명해 줘

 

A. ARC(Automatic Reference Counting)는 자동으로 메모리를 관리하는 기술로, 개발자가 메모리 관리를 수동으로 하지 않아도 됩니다. ARC를 사용하면, 객체가 참조되는 동안에만 메모리가 유지되고, 참조가 없어지면 자동으로 메모리가 해제됩니다.

 

ARC를 사용하는 Objective-C 코드에서는, 객체를 생성할 때 'alloc' 대신 'init' 메소드를 호출하면 자동으로 참조 횟수가 1 증가합니다. 참조를 저장할 변수를 선언할 때는 'strong' 속성을 사용하면 해당 객체가 유지되는 동안 참조 횟수가 증가합니다. 참조 변수의 값을 변경하거나 해당 변수가 스코프를 벗어날 때는 자동으로 참조 횟수가 감소하며, 참조 횟수가 0이 되면 자동으로 메모리가 해제됩니다.

 

아래는 ARC를 사용하는 Objective-C 코드의 예시입니다.

// 객체 생성 및 초기화
NSString *myString = [[NSString alloc] initWithString:@"Hello, World!"];

// 객체 사용
NSLog(@"%@", myString);

// 객체 참조 변수 선언
__strong NSString *myString2 = myString;

// 참조 변수의 값을 변경
myString2 = [[NSString alloc] initWithString:@"Hello, ARC!"];

// 참조 변수가 스코프를 벗어날 때 자동으로 메모리 해제

위 코드에서 'NSString' 객체를 생성할 때 'alloc' 대신 'init' 메소드를 사용하고, 참조 변수를 선언할 때 '__strong' 키워드를 사용합니다. 참조 변수의 값을 변경하면 이전 객체의 참조 횟수가 감소하고, 새로운 객체의 참조 횟수가 증가합니다. 마지막으로, 참조 변수가 스코프를 벗어나면 자동으로 메모리가 해제됩니다. 이와 같은 방식으로 ARC를 사용하면 개발자가 메모리 관리를 수동으로 하지 않아도 됩니다.

 

 

Q. ARC가 도입되었음에도 불구하고 메모리 관리 문제가 발생하는 경우는 어떤 경우인지 Objective-C 코드와 함께 설명해 줘

 

A. ARC가 도입되어 자동으로 메모리를 관리하지만, ARC를 사용하는 코드에서도 메모리 관리 문제가 발생할 수 있습니다. ARC를 사용하면 참조 횟수가 적절하게 관리되지만, 순환 참조(circular reference) 문제와 같은 다른 메모리 관리 문제가 발생할 수 있습니다.

 

순환 참조 문제는, 두 개 이상의 객체가 서로를 참조하는 경우 발생합니다. 이 경우 참조 횟수가 0이 되지 않아 메모리가 해제되지 않습니다.

아래는 순환 참조 문제가 발생하는 예시 코드입니다.

 

@interface MyObject : NSObject
@property (nonatomic, strong) MyObject *otherObject;
@end

@implementation MyObject
@end

MyObject *objectA = [[MyObject alloc] init];
MyObject *objectB = [[MyObject alloc] init];

objectA.otherObject = objectB;
objectB.otherObject = objectA;

위 코드에서 'MyObject' 클래스는 'otherObject' 속성을 가지며, 서로를 참조하도록 구현되어 있습니다.

'objectA'와 'objectB'는 서로를 참조하므로, 참조 횟수가 0이 되지 않아 메모리가 해제되지 않습니다.

 

이러한 순환 참조 문제를 해결하기 위해서는, 참조 관계를 끊어주는 것이 필요합니다.

일반적으로는, 참조 관계를 끊어주기 위해서 'weak' 속성이나 'unowned' 속성을 사용합니다.

이러한 속성을 사용하면, 객체가 해제될 때 자동으로 참조 관계가 끊어지므로 순환 참조 문제가 발생하지 않습니다.

 

아래는 'weak' 속성을 사용해서 순환 참조 문제를 해결한 예시 코드입니다.

@interface MyObject : NSObject
@property (nonatomic, weak) MyObject *otherObject;
@end

@implementation MyObject
@end

MyObject *objectA = [[MyObject alloc] init];
MyObject *objectB = [[MyObject alloc] init];

objectA.otherObject = objectB;
objectB.otherObject = objectA;

위 코드에서 'otherObject' 속성의 타입을 'weak'로 변경했습니다.

이제 'objectA'와 'objectB'가 서로를 참조하더라도 참조 횟수가 0이 되어 메모리가 해제됩니다.

 

Q. 'unowned' 속성을 사용해서 순환 참조 문제를 해결하는 Objective-C 코드도 보여줘

 

A. 'unowned' 속성은 ARC에서 참조 계수를 증가시키지 않고 객체에 접근할 수 있도록 하는 속성입니다.

이 속성은 'weak'와 다르게 객체가 메모리에서 해제되더라도 nil 값을 할당하지 않기 때문에,

참조한 객체가 언제나 존재한다는 것을 전제로 합니다.

 

아래는 'unowned' 속성을 사용해서 순환 참조 문제를 해결한 예시 코드입니다.

@interface MyObject : NSObject
@property (nonatomic, unowned) MyObject *otherObject;
@end

@implementation MyObject
@end

MyObject *objectA = [[MyObject alloc] init];
MyObject *objectB = [[MyObject alloc] init];

objectA.otherObject = objectB;
objectB.otherObject = objectA;

위 코드에서 'otherObject' 속성의 타입을 'unowned'로 변경했습니다.

이제 'objectA'와 'objectB'가 서로를 참조하더라도 참조 횟수가 증가하지 않고, 객체가 메모리에서 해제될 때 'otherObject' 속성에 nil이 할당되지 않습니다. 'unowned' 속성은 객체가 항상 존재함을 전제로 하기 때문에, 객체가 해제되지 않은 상태에서 'unowned' 속성에 접근하면 런타임 오류가 발생할 수 있으므로 주의해야 합니다.

 

 

 

출처: ChatGPT(https://chat.openai.com/chat)