Xcode 4와 동시에 등장한 ARC(Automatic Reference Counting) 덕분에, iOS 개발자들은 메모리 관리에서 어느정도 해방될 수 있었습니다. 그럼 ARC가 도입되기 전에는 어떤 방식으로 메모리를 관리했을까요?

이번 글과 다음 글에서는 ‘레퍼런스 카운팅’을 활용한 메모리 관리 방법에 대해 알아보려고 합니다. 레퍼런스 카운팅에 대한 내용이 궁금하다면 이전 글을 참고해주세요.

MRR (Manual Retain Release) ?

ARC가 등장하기 전, 개발자는 모든 객체의 레퍼런스 카운트를 직접 관리해야 했습니다. Apple에서는 이 방식을 MRR이라고 하며, 단어의 뜻 그대로 객체의 Retain과 Release를 직접 호출하는 방식을 뜻합니다.


Retain
NSObject 클래스의 함수이며, 객체의 레퍼런스 카운트를 ‘증가’시킵니다. 객체가 메모리에서 해제되지 않도록 하기 위해 이 함수를 호출하여 레퍼런스 카운트를 증가시킬 수 있습니다.

Release
NSObject 클래스의 함수이며, 객체의 레퍼런스 카운트를 ‘감소’시킵니다. 객체를 더이상 사용하지 않거나, 메모리에서 해제하고 싶을 때 이 함수를 호출하여 레퍼런스 카운트를 감소시킬 수 있습니다.


Example

Retain과 Release 함수를 호출하면, 객체의 레퍼런스 카운트가 어떻게 변하는지 샘플 코드를 통해 알아보겠습니다.

MyClass를 정의하고, dealloc 함수를 구현하여 객체가 메모리에서 해제될 때 “MyClass Released!” 라는 로그를 프린트 하도록 구현하였습니다.

그리고 viewDidLoad에서 MyClass객체를 생성하고, retain과 release를 번갈아 호출하면 아래와 같은 로그가 출력됩니다.

2019-10-31 23:23:08.926601+0900 ObjectiveC Example[47197:7510040] Count = 1
2019-10-31 23:23:08.926763+0900 ObjectiveC Example[47197:7510040] Count = 2
2019-10-31 23:23:08.926853+0900 ObjectiveC Example[47197:7510040] Count = 1
2019-10-31 23:23:08.926928+0900 ObjectiveC Example[47197:7510040] MyClass Released!

객체 생성 직후 1인 카운트가 retain을 호출하면 1 증가하는 것을 볼 수 있으며, release를 호출하면 카운트가 1 감소하는 것을 볼 수 있습니다.

카운트가 1일 때 한번 더 release를 호출하면 객체는 메모리에서 해제되는것을 볼 수 있습니다.

마치며

위 예제와 같이 객체의 유지 여부에 따라, 적절히 Retain과 Release 함수로 레퍼런스 카운트를 관리해주는 메모리 관리 기법을 MRR이라고 합니다.

레퍼런스 카운트에 영향을 미치는 함수는 위 2가지 외에도, 정말 많은 함수들이 존재합니다. alloc, new, copy, mutableCopy 등의 생성자와 NSArray에 추가 또는 삭제될 때 등, 레퍼런스 카운트는 수시로 영향을 받았습니다.

ARC가 등장하기 전 iOS 개발자들은 이런 방식으로 메모리를 관리했습니다. 로직을 구현하고 UI를 다듬기에도 바쁜데, 일일이 메모리 해제까지 신경 써야 했었죠. 😩

하지만, 이제 우리에겐 ARC라는 도구가 생겼습니다. 다음 글에서는 ARC에 대해 알아보도록 하겠습니다.

참고자료

Advanced Memory Management Programming Guide
Introducing Automatic Reference Counting