iOS Development Guide

ARC가 객체 생명주기를 어떻게 관리하는지

ARC(Automatic Reference Counting)는 클래스 인스턴스의 참조 수를 컴파일러가 자동으로 관리하는 메모리 모델이다. 핵심은 "할당/해제" 자체보다, 참조 그래프가 언제 0으로 떨어지는지 이해하는 것이다.

Memory Management Reference graph first Knowledge item #11
학습 날짜

기록 없음

핵심 개념

  • ARC는 참조 타입(class)만 대상으로 동작한다.
  • 강한 참조(strong)가 하나라도 남아 있으면 인스턴스는 해제되지 않는다.
  • 강한 참조 수가 0이 되는 순간 `deinit`이 호출되고 메모리가 정리된다.

왜 중요한가

iOS 앱의 메모리 문제 대부분은 "ARC를 모른다"가 아니라 "객체 간 참조 관계를 추적하지 못한다"에서 발생한다. ARC를 생명주기 관점으로 이해하면 누수와 조기 해제를 모두 줄일 수 있다.

동작 흐름 예시

final class UserSession {
    let id: String

    init(id: String) {
        self.id = id
        print("init \(id)")
    }

    deinit {
        print("deinit \(id)")
    }
}

func run() {
    var session: UserSession? = UserSession(id: "A")
    session = nil // strong reference 0 -> deinit
}
변수에 `nil`을 대입하는 행위 자체가 중요한 게 아니라, 그 시점에 남아 있는 strong reference 개수가 0인지가 핵심이다.

자주 헷갈리는 포인트

  • `struct`/`enum`은 값 타입이라 ARC 대상이 아니다.
  • 지역 변수 스코프 종료는 참조를 끊는 한 가지 계기일 뿐, 유일한 규칙은 아니다.
  • 클로저가 `self`를 캡처하면 추가 strong reference가 생길 수 있다.

strong / weak / unowned 차이

  • `strong`: 생명주기를 소유한다(기본값).
  • `weak`: 생명주기를 소유하지 않으며 대상 해제 시 자동으로 `nil`이 된다.
  • `unowned`: 소유하지 않지만 `nil`이 될 수 없다고 가정한다(잘못 쓰면 크래시).

실무 체크리스트

Then 1

ARC가 있으면 메모리 누수는 자동으로 없어지나요?

아니다. ARC는 참조 수 계산을 자동화할 뿐이다. 순환 참조처럼 strong reference가 서로 물고 있으면 참조 수가 0이 되지 않아 누수가 생긴다.

Then 2

`weak`를 많이 쓰면 안전한가요?

무조건 그렇지 않다. 소유해야 할 관계까지 `weak`로 만들면 객체가 예상보다 빨리 해제되어 로직이 깨질 수 있다. 소유 관계를 먼저 정의하고 그다음 참조 타입을 정해야 한다.