
iOS 애플리케이션을 개발할 때 메모리 관리는 중요한 주제 중 하나이다.
효율적인 메모리 관리 없이는 애플리케이션의 성능이 떨어질 수 있다.
이에 대응하여 Apple은 Automatic Reference Counting(ARC)를 도입하였다.
이번 글에서는 iOS에서의 ARC의 동작 원리에 대해 깊이 있게 알아본다.
ARC란?
ARC는 Automatic Reference Counting의 약자로, 객체의 참조 횟수를 자동으로 계산하여 객체의 메모리를 자동으로 관리하는 기술이다.
이를 통해 개발자는 복잡한 수명 주기 관리로부터 벗어나고, 메모리 누수나 중복 해제와 같은 문제를 최소화할 수 있다.
동작 원리
ARC는 코드를 컴파일 할 때 참조 횟수를 추적하고, 필요하지 않은 객체를 해제하는 코드를 자동으로 추가한다.
이는 실행 시간에 참조 카운트를 관리하는 것이 아니라 컴파일 타임에 이루어진다는 것을 의미한다.
class SampleClass {
var name: String?
init(name: String) {
self.name = name
print("\(name)이 초기화 되었습니다.")
}
deinit {
print("\(name!)이 해제 되었습니다.")
}
}
var instance: SampleClass? = SampleClass(name: "ARC Sample")
instance = nil위 코드에서 SampleClass의 인스턴스를 생성하고 nil로 설정하면, ARC는 deinit을 호출하여 객체를 메모리에서 해제한다.
Strong, Weak, Unowned 참조
ARC에서는 참조 타입에 따라 다양한 속성을 제공한다.
- Strong: 기본 참조 타입이다. 객체를 강하게 참조하여 해당 객체의 참조 카운트를 증가시킨다.
- Weak: 객체를 약하게 참조한다. 참조된 객체가 메모리에서 해제되면 자동으로 nil로 설정된다. 주로 delegate와 같은 곳에서 사용된다.
- Unowned:
Weak과 유사하지만 nil이 될 수 없다. 참조된 객체가 메모리에서 해제되면 런타임 오류가 발생할 수 있다.
순환 참조와 ARC
두 객체가 서로를 참조하는 경우, ARC는 객체를 메모리에서 제거할 수 없다.
이러한 문제를 순환 참조라고 한다.
Weak 및 Unowned 참조는 순환 참조 문제를 해결하기 위해 도입되었다.
class Person {
var name: String
var laptop: Laptop?
init(name: String) { self.name = name }
deinit { print("\(name) 해제") }
}
class Laptop {
var brand: String
weak var owner: Person?
init(brand: String) { self.brand = brand }
deinit { print("\(brand) 해제") }
}
var john: Person? = Person(name: "John")
var macbook: Laptop? = Laptop(brand: "Macbook")
john?.laptop = macbook
macbook?.owner = john
john = nil
macbook = nil위 코드에서 Person과 Laptop은 서로를 참조한다.
Weak 속성을 사용하여 순환 참조를 방지한다.
결론
iOS에서의 ARC는 메모리 관리를 훨씬 간편하게 만들어 준다.
그러나 ARC의 동작 원리와 특성을 제대로 이해하지 않으면 예기치 않은 문제에 직면할 수 있다.
따라서 ARC를 올바르게 사용하기 위해서는 그 작동 원리를 정확히 알아야 한다.

Weak 및 Unowned 참조가 뭔가요??