TIL: 클로저의 메모리 구조

Royce·2025년 3월 30일

Swift 문법

목록 보기
61/63

클로저의 캡처 (Capturing Values)

클로저는 왜 캡처를 사용하는가

  • 클로저는 외부 변수나 상수를 내부에서 사용할 수 있도록 캡처할 수 있다
  • 클로저가 외부 변수에 대한 참조를 유지하기 때문에 실행 시점에도 해당 값을 사용할 수 있다
  • 캡처된 값은 클로저가 메모리에 존재하는 동안 유지된다
  • 클로저가 변수에 저장되거나 함수의 반환값으로 사용될 때 주로 발생한다

캡처

  • 클로저가 자신이 정의된 외부의 변수나 상수를 참조할 수 있는 기능이다
  • 클로저는 외부에서 선언된 변수를 복사하지 않고 참조를 통해 유지한다
  • 클로저가 변수에 저장되거나 함수의 반환값이 되면 해당 변수는 힙 메모리에 유지된다
  • 이로 인해 클로저는 상태를 기억할 수 있으며, 동일한 참조를 여러 곳에서 공유할 수 있다

클로저가 외부 변수를 캡처하는 예

var total = 0  // 외부 변수

let accumulate = { (value: Int) -> Int in
    total += value  // 외부 변수 total을 캡처하여 누적
    return total
}

accumulate(2)  // 2
accumulate(3)  // 5
accumulate(5)  // 10

total = 100

accumulate(1)  // 101
  • 클로저는 변수 total을 캡처하고 있으므로 클로저 외부에서 total 값을 변경해도 영향을 준다
  • 클로저는 캡처된 변수의 메모리 주소를 참조하기 때문에 동일한 값을 공유한다

일반 함수 내부 함수는 캡처가 아니다

func execute(number: Int) -> Int {
    var result = 0

    func square(_ n: Int) -> Int {
        result += n * n
        return result
    }

    return square(number)
}

execute(number: 3)  // 9
execute(number: 4)  // 16
execute(number: 5)  // 25
  • 이 경우 내부 함수 square는 외부로 반환되지 않고 함수 내에서만 사용되므로 캡처가 발생하지 않는다
  • 함수가 끝나면 변수 result도 함께 사라진다
  • 매번 새로운 함수 실행으로 result는 초기화된다

내부 함수를 반환 → 캡처 발생

func createAdder() -> (Int) -> Int {
    var total = 0

    func add(_ num: Int) -> Int {
        total += num
        return total
    }

    return add
}

let adder = createAdder()

adder(1)  // 1
adder(2)  // 3
adder(3)  // 6
  • 함수 createAdder는 내부 함수 add를 반환한다
  • 반환 시점에 변수 total이 캡처되어 클로저와 함께 메모리에 남는다
  • 이후 addertotal 값을 누적하며 유지한다

클로저는 참조 타입이다

let copyAdder = adder

copyAdder(4)  // 10
adder(5)      // 15
  • addercopyAdder는 같은 클로저 인스턴스를 참조한다
  • 두 클로저는 동일한 total 값을 공유한다
  • 클로저는 참조 타입이기 때문에 변수에 복사해도 동일한 상태를 유지한다

변수에 저장하지 않고 바로 실행하면 캡처되지 않는다

createAdder()(1)  // 1
createAdder()(2)  // 2
createAdder()(3)  // 3
  • 클로저를 저장하지 않고 즉시 실행하면 매번 새로운 total이 생성된다
  • 따라서 값이 누적되지 않고 항상 초기값부터 시작한다
  • 캡처된 값은 클로저가 메모리에 살아있는 동안만 유지된다

정리 - 캡처와 메모리

  • 클로저는 주변 변수를 캡처할 수 있다
  • 캡처된 변수는 클로저와 함께 Heap 메모리에 저장된다
  • 클로저를 변수에 저장하거나 외부로 전달해야 캡처가 유지된다
  • 단순히 함수 내에서 실행하고 끝나는 경우 캡처되지 않는다

요약

  • 클로저는 외부 변수나 상수를 내부에서 사용할 수 있도록 캡처할 수 있다
  • 클로저가 반환되거나 변수에 저장될 때 캡처가 발생한다
  • 내부 함수가 외부로 반환되지 않으면 캡처가 일어나지 않는다
  • 클로저는 참조 타입으로 복사하더라도 상태를 공유한다
  • 저장되지 않고 즉시 실행되는 클로저는 캡처한 값을 유지하지 않는다
profile
iOS 개발자 지망생

0개의 댓글