-
[Swift] ARC 알아보기 (Auto Reference Counting)iOS/Swift 2020. 9. 4. 16:29
안녕하세요:)
오늘은 Swift의 메모리 관리 기법인 ARC에 대해 알아보겠습니다.
프로젝트를 진행하다 보니, 기능이 많고 변수들도 많아서 메모리 관리에 신경이 쓰이는 순간이 왔습니다.
그래서 Swift는 메모리 관리를 어떻게 하고 있는지 알아보도록 하겠습니다.
메모리 관리를 왜 해야 할까?
우선 본격적으로 메모리 관리에 대해 알아보기 전에, 왜 알아야 하는지부터 짚고 넘어가겠습니다.
앱의 성능을 유지하기 위해 메모리 관리와 유지는 기본입니다.
메모리 관리가 제대로 일어나지 않으면 Memory Leak, Dangling Pointer 등의 문제가 발생할 수 있습니다.
- Memory Leak: 사용되지 않는 데이터가 메모리 공간을 차지하고 있는 현상
- Dangling Pointer: 이미 메모리 할당이 해제된 주소로 메모리에 접근하는 현상
그렇기 때문에 앱 개발자인 우리들은 메모리 관리가 필수적으로 필요합니다.
Object-C에서의 메모리 관리
ARC라는 기법이 나오기 전에 Object-C에서는 MRC를 사용했습니다.
즉, 개발자들이 직접 메모리를 관리하는 코드를 작성하여 수동으로 메모리를 관리했습니다.
이렇게 수동으로 메모리를 관리하다 보면 코드의 간결성이 떨어지고 효율적이지 못합니다.
그래서 Swift에서는 ARC를 default로 사용하고 있으며, Object-C에서도 ARC 사용이 가능합니다.
ARC란?
우선 메모리 관리란 메모리 영역 중에서 Heap 영역을 관리하는 것입니다.
Stack은 자동으로 값들에 메모리 할당과 해제를 하지만 Heap은 개발자가 동적으로 할당하는 메모리 공간입니다.
즉, 관리가 필요한 영역입니다.
Heap은 참조형 자료형들이 저장되는 메모리 공간입니다.
Swift에서 struct, enum은 값 타입이므로 Stack에서 관리되고 class, closure의 참조형 타입들은 Heap에 저장됩니다.
메모리 관리란 Heap 영역에 참조형 자료형들이 얼마나 참조되었는지 카운팅 하여 메모리 할당과 해제를 합니다.
이것을 자동으로 해주는 것을 ARC라고 합니다.
ARC는 Auto Reference Counting으로 자동으로 참조 카운팅을 해주는 것입니다.
즉, 객체에 대한 참조 카운트를 관리하고 0이 되면 자동으로 메모리에서 객체를 해제합니다.
ARC의 메커니즘은 Swift Runtime이라는 Library에서 구현됩니다.
Swift Runtime은 동적 할당되는 모든 object를 HeapObject라는 구조체로 표현합니다.
HeapObject에서는 Swift에서 객체를 구성하는 모든 데이터를 포함하고 있습니다. (reference count와 type meta data)
마지막으로 ARC는 Run time에 계속 실행되는 것이 아니고, Compile time (build시)에 실행됩니다.
여기까지 알아봤는데, 이렇게 보면 ARC는 Compile time에 실행되는데 어떻게 동적으로 실행되는 것들의 reference count를 세고 메모리를 관리하는지 궁금해집니다.
ARC의 동작
위의 궁금증의 대답은 아래와 같습니다.
ARC는 Compile time에 개발자의 코드를 분석하여 자동으로 retain, release를 삽입하여 reference count를 관리하고, reference count가 0이 되면 deinit을 호출해서 메모리를 해제시킵니다.
- retain: reference count 증가를 통해 현재 scope에서 객체가 유지되는 것을 보장하는 것
- release: reference count를 감소시킨다. retain 후 더 이상 객체가 쓰이지 않을 때 release를 해서 카운트를 감소시킨다.
ARC를 통해 삽입된 코드는 run time에 실행되어 reference count를 retain , release로 관리합니다.
reference count가 0이 되면 deinit으로 해제합니다.
정리해보자면, 동적 할당으로 reference object가 생성되면 그 객체의 정보가 HeapObject라는 구조체로 관리됩니다.
HeapObject안에는 reference count도 포함되고, class에 대한 HeapObject를 통해 reference count 관리가 가능합니다.
reference count는 HeapObject 구조체에서 접근 가능합니다.
간단한 예제 코드
class Person { let name: String init(name: String) { self.name = name print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") } }
위와 같이 참조형인 Person class를 하나 만들어봤습니다.
var reference1: Person? var reference2: Person? var reference3: Person?
그리고 Person을 참조하는 변수 세 개를 만듭니다.
이때 Person의 reference count는 아직 0이기 때문에 메모리에 할당되지 않았습니다.
reference1 = Person(name: "John Appleseed")
그리고 1번 변수에 Person을 init 해주면 콘솔 창에 아래와 같이 뜨면서 reference count가 +1 됩니다.
reference2 = reference1 reference3 = reference1
그리고 2번 3번 변수는 1번 변수를 참조하도록 하겠습니다. 이렇게 되면 reference count가 +2가 되어 현재 3이 되겠죠.
reference1 = nil reference2 = nil
그 후에 두 개의 변수에 nil을 할당합니다. 이렇게 되면 reference count가 -2가 됩니다.
그러면 현재 reference count는 1이 되기 때문에 아직 deinit이 호출되지 않습니다.
reference3 = nil
마지막으로 3번째 변수를 nil로 할당하면 reference count가 -1 되면서 현재 reference count가 0이 됩니다.
그래서 deinit이 호출되고 메모리가 해제됩니다.
마무리
오늘은 메모리 관리에 대해 알아봤는데요.
더 알아보니까 순환 참조에 대해서도 자세히 알아봐야 할 것 같습니다!
오늘도 포스팅 봐주셔서 감사합니다 :)
참고 사이트
https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html
https://medium.com/@rkdthd0403/ios-arc-%EB%BF%8C%EC%8B%9C%EA%B8%B0-9b3e5dc23814
'iOS > Swift' 카테고리의 다른 글
Closure (2) (0) 2020.04.17 Closure (0) 2020.04.11 프로토콜 지향언어, Swift (3) (0) 2020.03.21 프로토콜 지향언어, Swift (2) (1) 2020.03.14 프로토콜지향 언어, Swift (1) (0) 2020.03.07