ARC (Automatic Reference Counting)
ARC 소개 (Introduction to ARC)
ARC (Automatic Reference Counting)는 Swift의 메모리 관리 모델로, 메모리 누수를 방지하고 객체의 생명주기를 자동으로 관리합니다. ARC는 객체가 메모리에서 해제될 시점을 결정하기 위해 참조 카운트를 사용합니다. 참조 카운트가 0이 되면 객체는 자동으로 해제됩니다.
class MyClass { var value: Int init(value: Int) { self.value = value } deinit { print("MyClass instance with value \(value) is being deinitialized") } } var instance: MyClass? = MyClass(value: 10) instance = nil // "MyClass instance with value 10 is being deinitialized"
강한 참조, 약한 참조, 미소유 참조 (Strong, Weak, and Unowned References)
강한 참조 (Strong References)
강한 참조는 기본 참조 유형으로, 객체를 참조하는 동안 객체의 참조 카운트를 증가시킵니다. 강한 참조를 가지고 있는 동안 객체는 메모리에서 해제되지 않습니다.
class StrongReferenceExample { var property: String init(property: String) { self.property = property } } var strongRef: StrongReferenceExample? = StrongReferenceExample(property: "Strong Ref") print(strongRef?.property) // "Strong Ref" strongRef = nil // 객체는 해제되지 않음, 메모리에서 제거되지 않음
약한 참조 (Weak References)
약한 참조는 객체의 참조 카운트를 증가시키지 않으며, 객체가 해제될 때 약한 참조는 자동으로 nil
로 설정됩니다. 주로 순환 참조를 방지하는 데 사용됩니다. 약한 참조를 선언할 때는 weak
키워드를 사용합니다.
class Person { var name: String var friend: Person? init(name: String) { self.name = name } } var alice: Person? = Person(name: "Alice") var bob: Person? = Person(name: "Bob") alice?.friend = bob bob?.friend = alice // 강한 참조의 순환 발생 alice = nil // alice와 bob의 메모리 해제되지 않음, 순환 참조 발생 bob = nil // 순환 참조로 인해 메모리 해제되지 않음
약한 참조를 사용하여 순환 참조를 방지할 수 있습니다.
class Person { var name: String weak var friend: Person? // 약한 참조를 사용 init(name: String) { self.name = name } } var alice: Person? = Person(name: "Alice") var bob: Person? = Person(name: "Bob") alice?.friend = bob bob?.friend = alice // 약한 참조를 사용하므로 순환 참조 방지 alice = nil // alice와 bob의 메모리 해제됨 bob = nil
미소유 참조 (Unowned References)
미소유 참조는 객체의 생명주기에 대한 소유권을 가지지 않지만, 객체가 해제된 후에도 참조를 유지하려고 시도합니다. 만약 참조하는 객체가 해제된 상태에서 미소유 참조를 사용하면 런타임 에러가 발생합니다. 미소유 참조를 선언할 때는 unowned
키워드를 사용합니다.
class Person { var name: String var apartment: Apartment? init(name: String) { self.name = name } } class Apartment { var unit: String unowned var tenant: Person init(unit: String, tenant: Person) { self.unit = unit self.tenant = tenant } } var alice: Person? = Person(name: "Alice") var apartment: Apartment? = Apartment(unit: "5A", tenant: alice!) print(apartment?.tenant.name) // "Alice" alice = nil // alice와 관련된 메모리 해제됨 print(apartment?.tenant.name) // 런타임 에러 발생
강한 참조와 약한 참조의 비교 (Comparing Strong and Weak References)
강한 참조는 객체가 메모리에서 해제되지 않도록 보장하며, 약한 참조는 객체의 생명주기와 관계없이 참조할 수 있습니다. 약한 참조는 객체가 해제될 때 자동으로 nil
로 설정되므로 순환 참조를 방지하는 데 유용합니다.
class Node { var value: Int var next: Node? init(value: Int) { self.value = value } } var first: Node? = Node(value: 1) var second: Node? = Node(value: 2) first?.next = second // 강한 참조 second?.next = first // 강한 참조의 순환 발생 first = nil // 순환 참조로 인해 메모리 해제되지 않음 second = nil
위의 예제에서 강한 참조의 순환을 방지하기 위해 약한 참조를 사용할 수 있습니다.
class Node { var value: Int weak var next: Node? // 약한 참조를 사용하여 순환 참조 방지 init(value: Int) { self.value = value } } var first: Node? = Node(value: 1) var second: Node? = Node(value: 2) first?.next = second second?.next = first // 약한 참조로 순환 참조 방지 first = nil // 메모리 해제됨 second = nil
이와 같이 Swift의 메모리 관리에서 ARC, 강한 참조, 약한 참조, 미소유 참조의 개념과 활용에 대해 상세하게 설명하고 다양한 예제를 제공했습니다.