본문 바로가기
아카이브/iOS

[iOS] iOS 메모리 관리 기법 - 2. Objective-C의 메모리 관리

by Mildwhale 2014. 4. 15.

1. 시작하며

이전 포스팅에서 메모리 관리 기법인 '레퍼런스 카운팅'에 대해 간단하게 알아 보았습니다. 이번 포스팅에서는 OS X와 iOS에서는 레퍼런스 카운팅을 이용하여 어떻게 메모리를 관리하는지 알아보겠습니다.


2. 레퍼런스 카운팅의 4가지 규칙

- 생성하는 객체는 소유권을 가진다.

- "retain"을 이용하여 객체의 소유권을 가질 수 있다.

- 필요하지 않은 객체는 소유권을 내주어야 한다.

- 소유하고 있지 않은 객체의 소유권을 내주어서는 안된다.

* 소유권 : reference count (Retain Count)


레퍼런스 카운팅 기법에서는 객체의 참조 대상을 알 필요가 없습니다. 대신 위 4가지의 규칙을 따르는 것이 전부입니다.

Objective-C 객체의 행동

Objective-C 메서드 

생성, 소유권 획득 

 alloc / new / copy / mutableCopy 

소유권 획득 

 retain 

소유권 포기

 release

소멸, 해제

 dealloc


위 표는 "생성", "소유권 획득", "소유권 포기", "소멸"에 대응하는 Objective-C의 메서드를 정리한 표 입니다. 프로그래머는 위 함수를 적절히 사용하여 객체를 생성하고, 소유권을 관리하고, 객체를 소멸하는 작업을 수행하게 됩니다.


엄밀히 말하면 위의 메서드들은 Objective-C에서 제공되는 메서드들이 아닙니다. 위 메서드들은 Apple의 Cocoa 프레임워크의 일부인 Foundation 프레임워크에서 제공되는 메서드입니다. NSObject클래스에 위 함수들이 정의되어 있습니다.

* Foundation의 내부적인 구현은 Apple의 OpenSource에서 확인하실 수 있습니다.


3. 객체의 생성과 소유권의 획득

객체의 생성은 alloc과 new를 이용합니다.

id obj = [[NSObject alloc] init];
id obj = [NSObject new];
/*
 * 객체 생성 및 소유권 획득
 */

Objective-C에서 [[NSObject alloc] init]과 [NSObject new]는 NSObject 객체를 생성하고, 사용 가능한 상태로 초기화를 하는 동작을 합니다. obj변수는 생성된 NSObject객체의 포인터를 가지게 됩니다.


4. 객체의 소유권 획득

3번 '객체의 생성과 소유권의 획득'에서 이상한점이 하나 있습니다. 바로 '소유권의 획득'이라는 과정이 없기 때문입니다. 여기서 알 수 있는 사실은 'alloc'과 'new'를 이용하여 객체를 생성하게 되면 소유권도 자동적으로 획득하게 된다는 것입니다.


그렇다면 추가적인 소유권이 필요할 때에는 어떻게 해야할까요? 바로 retain메서드를 이용하는 것 입니다. 

객체의 생성은 alloc과 new를 이용하는 방법도 있지만, 클래스 메서드를 이용하여 객체를 생성하는 방법도 있습니다. 이 방법은 Foundation 프레임워크의 NSArray를 예로 설명하겠습니다.


id obj = [[NSArray alloc] init]; // 객체 생성 후 소유권 획득
id obj = [NSArray array]; // 객체 생성

[obj retain]; // 소유권 획득

1번 라인은 객체를 생성하고 소유권까지 획득하게 됩니다. 반면에, 2번 라인은 객체를 생성하지만 소유권은 획득하지 않습니다. 4번 라인의 retain 함수를 호출하게 되면 비로소 객체의 소유권을 획득하게 됩니다.


5. 객체의 소유권을 내주기

2번 '레퍼런스 카운팅의 4가지 규칙'에서 '필요하지 않은 객체는 소유권을 내주어야 한다'는 규칙이 있습니다. 프로그래머는 NSObject의 release 메서드를 사용하여, 사용이 끝난 객체의 소유권을 내주어야 하는 의무가 있습니다. (메모리 관리를 위하여)


그렇다면 객체의 생성과 소유권 획득 / 반납(헤제) 과정을 코드로 확인해보겠습니다.

id obj = [[NSObject alloc] init]; // 객체 생성 및 소유권 획득
[obj release]; // 객체의 소유권 반납, 해제

id obj = [NSArray array]; // 객체 생성
[obj retain]; // 객체의 소유권 획득

[obj release]; // 객체의 소유권 반납, 해제