[swift] 클로저의 생명주기

클로저는 Swift에서 매우 강력하게 사용되는 개념 중 하나입니다. 클로저는 일급 객체로서, 함수와 마찬가지로 매개변수로 전달하거나 반환값으로 사용할 수 있습니다. 클로저에는 자체적인 생명주기가 있으며, 이에 대해 알아보겠습니다.

클로저의 생성

클로저는 다양한 방식으로 생성할 수 있습니다. 가장 간단한 형태는 다음과 같습니다.

let closure = {
    // 클로저의 내용
}

이렇게 생성된 클로저는 변수 closure에 할당됩니다. 클로저는 실제 실행되기 전까지는 메모리에 존재만 하고 실행되지 않습니다.

클로저의 사용

클로저는 주로 함수의 매개변수로 사용되거나 다른 함수 내부에서 호출됩니다. 예를 들어, map 함수는 클로저를 인자로 받고 해당 클로저를 배열의 모든 요소에 적용한 결과를 반환합니다.

let numbers = [1, 2, 3, 4, 5]

let squaredNumbers = numbers.map({ (number: Int) -> Int in
    return number * number
})

print(squaredNumbers) // [1, 4, 9, 16, 25]

위의 예제에서는 map 함수에 { (number: Int) -> Int in return number * number }라는 클로저를 전달했습니다. 이 클로저는 numbers 배열의 각 요소를 제곱하여 새로운 배열을 반환합니다.

클로저의 종료

클로저는 실행이 완료되면 메모리에서 해제됩니다. 그러나 주의해야 할 점은 클로저 내부에서 다른 객체들에 대한 강한 참조가 발생할 수 있다는 것입니다. 이러한 경우 메모리 누수가 발생할 수 있으므로 ARC(Automatic Reference Counting)를 통해 강한 참조 순환을 방지해야 합니다.

class SomeClass {
    var closure: (() -> Void)?

    func doSomething() {
        closure = {
            print("Hello, world!")
        }
    }
}

var instance: SomeClass? = SomeClass()
instance?.doSomething()
instance = nil

위의 예제에서 closure 변수는 SomeClass의 인스턴스 내부에서 클로저를 참조하고 있습니다. 그러나 instance 변수가 nil로 설정됨으로써 SomeClass의 인스턴스가 메모리에서 해제됩니다. 이로 인해 해당 클로저도 함께 메모리에서 해제됩니다.

결론

Swift에서 클로저는 유용한 기능 중 하나입니다. 클로저는 자체적인 생명주기를 가지고 있으며, 주로 다른 함수의 인자로 사용됩니다. 클로저의 사용 중에는 메모리 관리에 주의해야 하므로, 강한 참조 순환을 방지하기 위해 ARC를 활용해야 합니다.


참고자료