본문 바로가기
iOS/Swift

Swift) ARC

by Jiseong 2022. 2. 13.

ARC

ARC는 Automatic Reference Counting의 약자이다.

레퍼런스 카운트를 자동으로 해준다고 이름에서 바로 알 수 있다.

ARC의 이름..의 좀 더 깊은.. 뜻을 알기위해 ARC가 있기 전에 있던 방식을 알아보자

ARC 이전엔?

ARC가 있기 전엔 MRC(Manual Reference Counting)라는 것이 있었다.

MRC도 마찬가지로 MANUAL이란 이름에서 알 수 있듯이 레퍼런스 카운트를 수동으로 해주었다는 것을 알 수 있다.

retain, new, alloc등을 사용해 레퍼런스 카운트를 올리고, release 등을 사용하여 레퍼런스 카운트를 내려 레퍼런스 카운트가 0이 되면 클래스 인스턴스를 deinit 시켜줬었다.

ARC는 그럼 뭔데요

MRC 방식은 RC를 언제 올려주고, 내려줄지 시점까지 생각함과 동시에, 수동으로 release, retain 등을 기입하면서까지 개발자가 신경써야했었다.

하지만 MRC와 달리 ARC는 컴파일타임에 자동으로 코드를 분석하여 적절하게 RC를 올려주고 내려주는 release, retain 등을 기입해준다. 

그렇게 ARC가 자동으로 기입한 release, retain등의 코드로 인해 레퍼런스 카운트가 오르내리며, 결국 0이되면 deinit을 호출하여 메모리에서 해제되는 것이다.

ARC가 자동으로 기입한 release, retain 등의 코드는 실제 코드에 보이지 않는다.

여까진 오케이다.. 근데..

Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects.

Instead of you having to remember when to use retain, release, and autorelease, ARC evaluates the lifetime requirements of your objects and automatically inserts appropriate memory management calls for you at compile time. The compiler also generates appropriate dealloc methods for you. In general, if you’re only using ARC the traditional Cocoa naming conventions are important only if you need to interoperate with code that uses manual reference counting.

TransitioningToARC

컴파일타임에 일어나는 일임을 설명하고, 일어나는 일에 대한 설명이다.

근데 컴파일 시점에 ARC가 동작하고 말면, 컴파일 시점에 메모리에 올라가지 않는 것들은 어떻게 관리를 하는걸까?

위 사진은 MRC와 ARC의 비교이다.

 

MRC는 직접 개발자가 retain/release 코드를 삽입해줘야 하는 반면, ARC는 코드 전체를 분석하여 자동으로 retain/release 코드가 들어가야할 곳을 판단하여 들어가기 때문에 코드수가 현저히 줄어든다.

 

Complie 시점에 메모리에 올라가지 않는 것도 코드상엔 위치하고 있기 때문에 Complie 시점에 판단하여 retain/release 코드를 넣어준다. 

 

그렇게 삽입된 코드들은 Runtime 중 실행되기 때문에 "컴파일 시점에 ARC가 동작하고 말면, 컴파일 시점에 메모리에 올라가지 않는 것들은 어떻게 관리를 하는걸까?" 같은 걱정은 하지 않아도 된다는 것이다.

 

이렇게 ARC가 메모리를 자동으로 추적하고 관리해주기 때문에 애플에선 "얘(ARC)가 해줄거니깐 너넨 메모리 관리 따로 안해도 돼" 라고 한다.

 

하지만 메모리 순환 참조가 발생할 시 어느 하나의 클래스 인스턴스의 레퍼런스 카운트가 0이 되지않아 메모리에서 자동 해제되지 않는 문제가 발생할 수 있기때문에 순환 참조를 방지, 해결하기 위한 방법을 필수적으로 알아야 한다.

ARC Example

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    deinit {
        print("Person deinit")
    }
}

var john: Person? = Person(name: "John", age: 36) // RC + 1
var doppelganger = john // RC + 1

인스턴스 프로퍼티 john, doppelganger는 Stack에 할당되고 클래스 인스턴스는 Heap에 할당됨 Stack의 john과 doppelganger엔 Heap에 위치한 클래스 인스턴스의 주소값이 들어간다.

john = nil  // RC - 1

클래스 인스턴스를 참조하는 놈이 하나 줄어들었다.

그러니 RC - 1

doppelganger = nil // RC -1

하나 더 줄었다. RC - 1

RC가 0이 됐네?

deinit 호출, 메모리 해제

결과

다음엔 참조순환 해결 방법에 대해 알아보자

마우스로 그림 그리기 드럽게 힘드네

'iOS > Swift' 카테고리의 다른 글

Swift) weak, unowned  (0) 2022.02.13
Swift) 순환 참조 , strong, weak  (0) 2022.02.13
Swift) Protocol(1)  (0) 2022.02.13
Swift) removeAll() vs []  (0) 2022.02.13
Swift) map  (0) 2022.02.12

댓글