클로저(Closure)는 스위프트( Swift)에서 매우 강력한 개념으로, 코드 조각을 캡슐화하고 변수나 상수를 캡처하여 다른 곳에서 사용할 수 있게 해줍니다.
하지만 클로저를 사용할 때는 메모리 관리에 신경을 써야 합니다. 클로저 내부에서 강한 순환 참조가 발생하지 않도록 주의해야 하며, 메모리 누수를 방지할 수 있는 방법을 알아야 합니다.
강한 순환 참조
강한 순환 참조는 서로를 참조하는 객체가 메모리에 남아있는 상태를 의미합니다. 이는 클로저와 관련하여 특히 중요한 문제입니다. 예를 들어, 클래스의 프로퍼티로 클로저를 할당하고 해당 클로저에서 프로퍼티를 참조하는 경우, 프로퍼티와 클로저간 강한 순환 참조가 발생할 수 있습니다.
class MyClass {
var closure: (() -> Void)?
init() {
closure = {
self.doSomething()
}
}
func doSomething() {
// Some code here
}
}
위의 예제에서 closure
은 MyClass
의 인스턴스가 메모리에서 해제되기 전까지 메모리에 계속 남아있습니다. 따라서 MyClass
인스턴스가 참조하는 다른 객체들도 메모리에서 해제되지 않습니다.
강한 순환 참조 해결 방법
강한 순환 참조를 해결하기 위해 Swift에서는 클로저 캡처 리스트(Capture List)를 제공합니다. 클로저 캡처 리스트는 클로저 내부에서 참조한 변수나 상수를 약한(weak)이나 미소유(unowned) 참조로 캡처할 수 있도록 해줍니다.
class MyClass {
var closure: (() -> Void)?
init() {
closure = { [weak self] in
self?.doSomething()
}
}
func doSomething() {
// Some code here
}
}
위의 예제에서 [weak self]
를 사용하여 self
를 약한 참조로 캡처하여 강한 순환 참조를 방지합니다. 이렇게 하면 MyClass
인스턴스가 메모리에서 해제될 때 클로저도 함께 해제됩니다.
결론
클로저는 강력한 기능이지만, 메모리 관리를 신경써야 하는 부분입니다. 강한 순환 참조를 피하기 위해 클로저 캡처 리스트를 사용하는 것이 중요합니다. 약한 참조나 미소유 참조를 적절히 활용하여 메모리 누수를 방지하고 안정적인 애플리케이션을 구현할 수 있습니다.
참고 자료
- Apple Developer Documentation - Automatic Reference Counting
- Swift By Sundell - Capturing values in Swift closures