1. 강한 참조(Strong Reference)란?
Swift에서 강한 참조(Strong Reference)는 객체의 소유권을 유지하는 참조 방식입니다. 기본적으로 모든 참조는 강한 참조로 설정되며, 객체가 다른 객체를 강한 참조하면 참조 카운트가 증가하여 그 객체가 메모리에서 해제되지 않도록 보장됩니다.
특징
- 기본 참조 방식으로, 객체의 소유권을 유지합니다.
- 객체를 참조하는 동안 메모리에서 해제되지 않습니다.
- 순환 참조를 발생시킬 수 있으므로, 상호 참조가 필요한 경우 주의해야 합니다.
사용 예시
강한 참조는 대부분의 상황에서 사용되며, 객체가 독립적으로 존재할 때 적합합니다.
class Person {
var name: String
var pet: Pet? // 기본적으로 강한 참조
init(name: String) {
self.name = name
}
}
class Pet {
var type: String
var owner: Person? // 기본적으로 강한 참조
init(type: String) {
self.type = type
}
}
let john = Person(name: "John")
let cat = Pet(type: "Cat")
john.pet = cat
cat.owner = john
설명
위 코드에서는 Person
객체 john
과 Pet
객체 cat
이 서로를 강한 참조합니다. 이 경우, john
과 cat
이 서로를 참조하고 있기 때문에, 순환 참조(Circular Reference)가 발생할 수 있습니다. 이로 인해 john
과 cat
은 서로를 참조한 채 메모리에서 해제되지 않습니다. 이를 해결하려면 약한 참조 또는 unowned 참조를 사용해야 합니다.
2. 약한 참조(Weak Reference)란?
약한 참조(Weak Reference)는 객체의 소유권을 유지하지 않는 참조 방식입니다. 약한 참조는 객체가 더 이상 사용되지 않을 때 메모리에서 해제될 수 있도록 하며, 순환 참조를 방지하는 데 주로 사용됩니다. 약한 참조는 항상 옵셔널(Optional
) 타입으로 선언되어야 하며, 객체가 해제되면 자동으로 nil
로 설정됩니다.
특징
- 객체의 소유권을 유지하지 않고, 객체가 해제되면 자동으로
nil
로 설정됩니다. - 약한 참조는 항상 옵셔널 타입으로 선언되어야 합니다.
- 순환 참조를 방지할 때 주로 사용됩니다.
사용 예시
약한 참조는 보통 상호 참조를 방지하기 위해 한쪽의 참조를 약한 참조로 설정합니다.
class Person {
var name: String
var pet: Pet? // 강한 참조
init(name: String) {
self.name = name
}
}
class Pet {
var type: String
weak var owner: Person? // 약한 참조
init(type: String) {
self.type = type
}
}
let john = Person(name: "John")
let cat = Pet(type: "Cat")
john.pet = cat
cat.owner = john // 약한 참조이므로 순환 참조 방지
설명
위 코드에서 owner
속성은 weak
키워드를 사용하여 약한 참조로 선언되었습니다. 따라서 Person
인스턴스가 메모리에서 해제되면 Pet
인스턴스의 owner
속성은 자동으로 nil
로 설정됩니다. 이로써 순환 참조 없이 두 객체가 서로 참조할 수 있습니다.
3. Unowned 참조란?
Unowned 참조는 약한 참조와 비슷하게 객체의 소유권을 유지하지 않으면서 참조하는 방식입니다. 하지만 약한 참조와 다르게 Optional
이 아니며, 참조가 항상 메모리에 존재한다고 확신할 때 사용합니다. 객체가 해제된 후에 unowned
참조에 접근하면 런타임 오류가 발생하므로, 수명이 보장된 경우에만 사용해야 합니다.
특징
- nil을 허용하지 않는 비옵셔널 참조입니다.
- 객체의 소유권을 유지하지 않으므로, 메모리 해제에 영향을 미치지 않습니다.
- 참조 대상보다 수명이 짧거나 종속적인 객체에 적합합니다.
사용 예시
unowned 참조는 보통 참조 대상이 항상 유효할 것으로 확신할 때 사용합니다.
class Company {
var name: String
var ceo: Employee?
init(name: String) {
self.name = name
}
}
class Employee {
var name: String
unowned var company: Company // unowned 참조
init(name: String, company: Company) {
self.name = name
self.company = company
}
}
let apple = Company(name: "Apple")
let tim = Employee(name: "Tim", company: apple)
apple.ceo = tim
설명
위 코드에서 Employee
의 company
속성은 unowned 참조로 선언되었습니다. 이 설정으로 Employee
는 Company
객체가 해제될 때까지 company
속성을 참조할 수 있습니다. Employee
는 항상 Company
와 함께 해제되므로 순환 참조의 위험 없이 안전하게 참조할 수 있습니다.
4. 참조 타입의 사용 시기와 사례
Swift에서는 메모리 관리와 객체 간의 관계를 명확히 하기 위해 참조 타입을 상황에 맞게 사용합니다.
참조 타입 | 사용 시기 및 사례 |
---|---|
강한 참조 | 기본적인 참조 방식으로, 객체 간의 단방향 참조에 적합합니다. 순환 참조가 발생하지 않을 때 대부분 강한 참조를 사용합니다. |
약한 참조 | 순환 참조가 발생할 수 있는 경우에 사용합니다. 예를 들어, 부모-자식 관계에서 자식이 부모를 약한 참조로 설정하여 순환 참조를 방지합니다. |
Unowned 참조 | 참조 대상이 항상 메모리에 남아있거나 한쪽 객체가 다른 객체에 종속적인 경우 사용합니다. 예를 들어, Company 와 Employee 에서 Employee는 항상 Company에 종속적이므로 unowned 로 설정합니다. |
5. 요약
Swift의 강한 참조, 약한 참조, unowned 참조는 객체 간의 관계를 정의하고, 메모리 관리 및 순환 참조 문제를 해결하기 위해 중요한 역할을 합니다.
- 강한 참조는 기본적인 참조 방식으로, 객체의 소유권을 유지합니다.
- 약한 참조는 순환 참조를 방지하고, 객체가 해제될 때
nil
로 설정됩니다. - Unowned 참조는 객체가 항상 메모리에 존재할 때 사용하며, 순환 참조 없이 비옵셔널 참조를 가능하게 합니다.
최종 정리
이와 같이 참조 방식을 상황에 맞게 선택하여 객체 간의 관계를 설정하고 메모리 관리를 효율적으로 할 수 있습니다. Swift의 자동 메모리 관리(ARC) 덕분에, 개발자는 강한 참조와 약한 참조를 적절히 사용하여 메모리 누수 없이 안전한 코드를 작성할 수 있습니다.
'프로그래밍공부(Programming Study) > IOS 개발' 카테고리의 다른 글
Swift의 `mutating` 키워드, 언제 사용해야 할까? (4) | 2024.11.11 |
---|---|
SwiftUI에서 Class와 Struct, 언제 어떻게 사용해야 할까? Swift 초보자를 위한 가이드 (1) | 2024.11.11 |
Swift 클로저와 콜백 함수의 모든 것 - 개념, 문법, 특징, 코드 예제 완벽 정리 (4) | 2024.11.09 |
Swift 프로퍼티 초기화와 앱 진입점의 엄격한 초기화 규칙 (2) | 2024.11.09 |
SwiftUI에서 some View와 Opaque Return Type 그리고 Preview의 개념과 활용법 (8) | 2024.10.28 |
댓글