본문 바로가기

카테고리 없음

내가 몰라서 쓰는 스위프트(26) ARC란?

ARC(Automatic Reference Counting)는 Swift에서 메모리 관리를 자동으로 해주는 시스템입니다. ARC는 객체가 언제 메모리에서 해제되어야 하는지를 자동으로 추적하고 관리하여, 개발자가 수동으로 메모리를 할당하거나 해제할 필요 없이 안정적으로 앱을 개발할 수 있게 해줍니다.

ARC의 작동 방식

  1. 참조 카운팅:
    • Swift의 모든 클래스 인스턴스는 참조 카운트를 가지고 있습니다. 이 카운트는 해당 인스턴스를 참조하는 변수나 상수가 얼마나 많은지를 나타냅니다.
    • 새로운 인스턴스가 생성되면 참조 카운트는 1이 됩니다.
    • 인스턴스가 다른 변수나 상수에 할당될 때마다 참조 카운트가 증가합니다.
    • 반대로, 변수가 더 이상 인스턴스를 참조하지 않을 때 참조 카운트는 감소합니다.
  2. 메모리 해제:
    • 참조 카운트가 0이 되는 순간, ARC는 해당 인스턴스를 메모리에서 자동으로 해제합니다. 즉, 더 이상 사용되지 않는 메모리를 반환하여 앱의 메모리 사용을 최적화합니다.

 

class Person {
    let name: String
    
    init(name: String) {
        self.name = name
        print("\(name) is initialized")
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

var person1: Person? = Person(name: "John") // 참조 카운트 1
var person2 = person1 // 참조 카운트 2

person1 = nil // 참조 카운트 1
person2 = nil // 참조 카운트 0, 메모리 해제됨

 

위 코드에서 Person 객체는 person1과 person2가 참조하고 있을 때 참조 카운트가 2입니다. person1이 nil이 되면 참조 카운트는 1이 되고, person2도 nil로 설정되면 참조 카운트가 0이 되어 메모리에서 해제됩니다. 해제될 때 deinit 메서드가 호출되어 메모리 해제가 완료됨을 알립니다.

강한 참조 사이클 (Retain Cycle)

ARC가 참조 카운트 방식으로 메모리를 관리하다 보면 강한 참조 사이클 문제가 발생할 수 있습니다. 두 개 이상의 객체가 서로를 강하게 참조하고 있으면 참조 카운트가 0이 되지 않아 메모리에서 해제되지 않습니다. 이 문제를 방지하려면 약한 참조(weak) 또는 **비소유 참조(unowned)**를 사용해야 합니다.

class Person {
    let name: String
    var apartment: Apartment?
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?
    
    init(unit: String) {
        self.unit = unit
    }
    
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")

john?.apartment = unit4A
unit4A?.tenant = john

// Apartment는 Person을, Person은 Apartment를 참조하는상황

john = nil // john이 nil이 되어도 참조 카운트는 0이 되지 않음
unit4A = nil // 강한 참조 사이클로 인해 메모리 해제되지 않음

 

이 문제는 weak 키워드를 사용하여 해결할 수 있습니다. 예를 들어, Apartment 클래스의 tenant 속성을 weak로 선언하면, Person 인스턴스가 강한 참조에서 벗어나 메모리에서 해제될 수 있습니다.

class Apartment {
	weak var tenant: Person?
}

 

요약

  • ARC(Automatic Reference Counting): Swift에서 클래스 인스턴스의 메모리를 자동으로 관리하는 시스템.
  • 참조 카운트 증가/감소: 인스턴스가 참조될 때 카운트가 증가하고, 참조가 사라지면 감소.
  • 메모리 해제: 참조 카운트가 0이 되면 인스턴스는 메모리에서 해제됨.
  • 강한 참조 순환: 두 객체가 서로 강하게 참조할 때 발생하는 문제로, weak나 unowned 키워드를 사용해 해결 가능.

이렇게 ARC는 개발자가 직접 메모리 관리를 신경 쓰지 않아도 효율적으로 메모리를 관리해 주지만, 강한 참조 순환 문제는 주의해서 해결해야 합니다.