캡처 목록과 약한 self
[weak self]로 순환 참조를 방지합니다.
캡처 목록과 약한 self은(는) CoddyKit의 무료 Swift Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Swift Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
참조 순환 위험
객체가 self를 강하게 캡처하는 탈출 클로저를 저장하면 서로가 상대방을 영원히 유지하게 됩니다 — 메모리 누수를 일으키는 참조 순환입니다.
강한 참조 순환
클로저는 self를 강하게 캡처하고 self는 클로저를 보유하므로 둘 다 해제되지 않습니다:
class Owner {
var onEvent: (() -> Void)?
func setup() {
onEvent = { print(self.describe()) } // strong self -> cycle
}
func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?() // "Owner" (but leaks)캡처 목록
클로저 시작 부분의 캡처 목록 { [weak self] in ... }은 캡처한 각 참조를 보관하는 방식을 제어합니다. 강한 참조 대신 weak 또는 unowned를 사용할 수 있습니다.
weak self로 순환 끊기
[weak self]는 self를 선택 사항으로 캡처하므로 self를 계속 유지하지 않습니다:
class Owner {
var onEvent: (() -> Void)?
func setup() {
onEvent = { [weak self] in
print(self?.describe() ?? "gone")
}
}
func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?() // "Owner" (no cycle)weak를 사용하면 self가 선택 사항이 됩니다
[weak self]를 사용하면 self가 Self?가 되므로 언래핑해야 합니다:
class Worker {
var tag = "W"
lazy var job: () -> Void = { [weak self] in
guard let self = self else { return }
print(self.tag)
}
}
let w = Worker()
w.job() // "W"guard let self 패턴
self를 일찍 다시 바인딩하면 클로저의 나머지 부분에서 강한 비선택적 참조를 사용할 수 있습니다:
class Service {
var name = "S"
lazy var run: () -> Void = { [weak self] in
guard let self else { return }
print(self.name)
print("still \(self.name)")
}
}
Service().run() // "S" / "still S"weak와 unowned 비교
weak는 선택적 참조를 제공하므로 객체가 이미 사라졌을 때도 안전합니다. unowned는 비선택적이고 더 빠르지만 객체가 해제된 후 접근하면 충돌합니다 — self가 클로저보다 반드시 오래 유지되는 경우에만 사용하세요.
unowned 사용하기
클로저가 self보다 오래 유지될 수 없을 때 unowned를 선택하세요:
class Timer2 {
var ticks = 0
lazy var tick: () -> Void = { [unowned self] in
self.ticks += 1
}
}
let t = Timer2()
t.tick(); t.tick()
print(t.ticks) // 2특정 속성 캡처하기
self 전체 대신 필요한 항목만 캡처하세요 — 때로는 이렇게 하면 순환을 완전히 피할 수 있습니다:
class VM {
let id = 42
lazy var printer: () -> Void = { [id] in print(id) }
}
VM().printer() // 42비탈출 클로저에는 weak가 필요하지 않습니다
map처럼 동기적으로 실행되는 비탈출 클로저는 순환을 만들지 않으므로, 그 안에서 self를 강하게 캡처해도 괜찮습니다:
class Calc {
let factor = 3
func scale(_ xs: [Int]) -> [Int] {
xs.map { $0 * self.factor } // safe, non-escaping
}
}
print(Calc().scale([1, 2])) // [3, 6]기억해 둘 원칙
self를 참조하는 저장된 탈출 클로저에는 [weak self]를 사용하세요. self가 살아 있다고 보장되는 경우에만 unowned를 선택하세요. 비탈출 클로저에는 캡처 목록을 생략하세요.
class P {
var n = "P"
var stored: (() -> Void)?
func arm() { stored = { [weak self] in print(self?.n ?? "-") } }
}
let p = P(); p.arm(); p.stored?() // "P"빠른 확인
저장된 탈출 클로저에서 [weak self]를 사용하는 이유는 무엇인가요?
복습
캡처 목록에 대해 배웠습니다:
- 저장된 탈출 클로저에서 self를 강하게 캡처하면 참조 순환이 생깁니다(메모리 누수)
[weak self]가 순환을 끊고 self가 선택 사항이 되므로guard let self을 사용합니다unowned는 비선택적이고 더 빠르지만 self가 사라진 후 접근하면 충돌합니다- 비탈출 클로저에는 캡처 목록이 필요하지 않습니다
다음: 오토클로저
자주 묻는 질문
“캡처 목록과 약한 self” 강의는 무료인가요?
네 — “캡처 목록과 약한 self” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Swift Academy 강의 전체를 잠금 해제할 수 있습니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“캡처 목록과 약한 self”에서 뭘 배우나요?
[weak self]로 순환 참조를 방지합니다. 브라우저에서 직접 실행하는 실습 코드로 Swift Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Swift Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Swift Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“캡처 목록과 약한 self” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Swift Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Swift Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 참조로 값 캡처하기
- 이스케이핑 클로저
- 캡처 목록과 약한 self
- 자동 클로저