Swift Memory Management


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, 강한 참조, 약한 참조, 미소유 참조의 개념과 활용에 대해 상세하게 설명하고 다양한 예제를 제공했습니다.


Leave a Reply

Your email address will not be published. Required fields are marked *