내일배움캠프 34일차

임클·2025년 4월 17일

내일배움캠프

목록 보기
35/44
post-thumbnail

1. ARC(Automatic Reference Counting)의 동작 원리

  • Swift의 ARC는 런타임에서 인스턴스에 대한 강한 참조(strong reference)를 추적하여, 참조 카운트(reference count)가 0이 되면 메모리를 해제하는 자동 메모리 관리 기법입니다.

  • 인스턴스를 생성하면 참조 카운트가 1로 시작하고, 인스턴스를 가리키는 변수나 상수가 strong으로 선언될 때마다 카운트가 +1, 해제될 때마다 –1이 됩니다.

  • 예시:

    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) deinitialized") }
    }
    
    var a: Person? = Person(name: "Alice")  // 카운트 1
    var b = a                              // strong 복사 → 카운트 2
    a = nil                                // 카운트 1
    b = nil                                // 카운트 0 → deinit 호출, 메모리 해제

2. Retain Cycle(순환 참조) 방지 방법

  • 순환 참조는 두 객체가 서로를 strong으로 참조하여 참조 카운트가 0이 되지 않는 상황을 말합니다.
  • 대표 사례: 뷰 컨트롤러와 클로저, 부모-자식 참조 관계, delegate 패턴 등.
  • 해결책
    1. weak 참조
      • 참조 대상이 해제되어도 자동으로 nil이 되도록 선언
      • 옵셔널 타입에만 적용 가능
      class Parent {
          var child: Child?
      }
      class Child {
          weak var parent: Parent?
      }
    2. unowned 참조
      • 항상 해제되지 않는(non‑nil) 관계에서 사용
      • 해제된 뒤 접근 시 런타임 크래시
      class Customer {
          let card: CreditCard
          init() { card = CreditCard(owner: self) }
      }
      class CreditCard {
          unowned let owner: Customer
          init(owner: Customer) { self.owner = owner }
      }
    3. 클로저 캡처 리스트
      • 클로저가 self를 strong 캡처할 때 순환 참조 발생
      • [weak self] 또는 [unowned self]를 명시
      class ViewController {
          lazy var handler: () -> Void = { [weak self] in
              guard let self = self else { return }
              self.doSomething()
          }
      }

3. deinit 메서드 호출 시점 및 역할

  • 클래스 인스턴스의 참조 카운트가 0이 되는 순간, ARC가 메모리를 해제하기 직전에 deinit이 한 번 호출됩니다.
  • deinit 내부에서는 리소스 해제, 옵저버 제거, Notification 해제, 파일 닫기 등 메모리 외의 클린업 작업을 처리할 수 있습니다.
  • 예시:
    class FileHandler {
        let handle: FileHandle
        init(path: String) { handle = FileHandle(forReadingAtPath: path)! }
        deinit {
            handle.closeFile()
            print("파일 핸들러 해제")
        }
    }

배운 점

  • ARC는 참조 카운트를 기반으로 메모리를 자동 해제하되, 순환 참조를 직접 방지해야 함을 이해했다.
  • weakunowned의 차이를 명확히 구분하여 적절히 사용해야 한다.
  • deinit은 단순히 메모리 해제뿐 아니라, 외부 리소스 해제에도 중요한 역할을 한다.

0개의 댓글