클로저의 실행 시점과 키워드 이해
클로저는 왜 @escaping이 필요한가
- 기본적으로 함수가 종료되면 파라미터로 전달된 클로저도 함께 메모리에서 해제된다
- 하지만 클로저가 함수 종료 이후에도 실행되어야 할 경우, 클로저는 함수의 실행 스코프를 "탈출"해야 한다
- 이럴 때 사용하는 키워드가
@escaping이다
- 대표적으로 비동기 처리(GCD), 클로저 저장 등에서 사용된다
함수 내부에서 즉시 실행되는 클로저
func executeNow(closure: () -> Void) {
print("함수 시작")
closure()
print("함수 종료")
}
executeNow {
print("클로저 실행")
}
- 이 경우 클로저는 함수 내부에서 즉시 실행되는 구조이다
- 함수의 실행 흐름을 벗어나지 않으므로
@escaping이 필요하지 않다
- 함수가 종료되면 클로저도 메모리에서 함께 사라진다
클로저를 외부 변수에 저장하는 경우 @escaping 필요
var storedClosure: (() -> Void)? = nil
func storeClosure(closure: @escaping () -> Void) {
storedClosure = closure
}
storeClosure {
print("나중에 실행될 클로저")
}
storedClosure?()
- 클로저가 함수 외부에 저장되어 함수 실행이 끝난 후에도 사용되므로
@escaping이 필요하다
@escaping이 없으면 컴파일 오류가 발생한다
- 함수의 실행 흐름을 벗어나 클로저가 나중에 실행되는 경우에 해당한다
GCD 비동기 처리에서의 escaping
func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
completion("데이터 수신 완료")
}
}
fetchData { result in
print(result)
}
- 클로저가 비동기적으로 실행되기 때문에 함수가 종료된 이후에 클로저가 실행된다
- 따라서
@escaping이 필수로 필요하다
@autoclosure 키워드는 왜 사용하는가
@autoclosure는 표현식을 클로저로 자동 변환해주는 키워드이다
- 클로저의 실행을 지연시킬 수 있으며, 호출 시점에 표현식이 평가된다
- 주로 간단한 조건 판단이나 지연 평가가 필요한 곳에 사용된다
@autoclosure는 파라미터가 없는 클로저에만 사용 가능하다
@autoclosure 없이 직접 클로저 전달
func check(_ condition: () -> Bool) {
if condition() {
print("조건이 참이다")
} else {
print("조건이 거짓이다")
}
}
check({ 1 < 2 })
@autoclosure 사용으로 표현식만 전달
func checkAuto(_ condition: @autoclosure () -> Bool) {
if condition() {
print("조건이 참이다")
} else {
print("조건이 거짓이다")
}
}
checkAuto(1 < 2)
@autoclosure를 사용하면 호출 측에서는 클로저 문법 없이 표현식만 넘길 수 있다
- 표현식은 클로저로 감싸져 있다가, 함수 내부에서 실제로 평가된다
@autoclosure와 @escaping 함께 사용
func delayedPrint(_ message: @autoclosure @escaping () -> String) {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print(message())
}
}
delayedPrint("출력은 2초 뒤에")
@autoclosure는 기본적으로 non-escaping이다
- 비동기적으로 실행하기 위해서는
@escaping과 함께 사용해야 한다
요약 비교
| 상황 | @escaping 필요 여부 | 설명 |
|---|
| 함수 내에서 즉시 실행 | 필요 없음 | 함수 스코프 내에서 클로저 실행됨 |
| 클로저를 외부 변수에 저장 | 필요 | 클로저가 함수 스코프를 벗어남 |
| 비동기 처리 (GCD 등) | 필요 | 함수가 종료된 후 클로저가 실행됨 |
| 간단한 표현식 처리 | 필요 없음 | @autoclosure로 자동 처리됨 |
@autoclosure + 비동기 처리 | 필요 | 평가를 지연하고 나중에 실행됨 |
요약
@escaping은 클로저가 함수 종료 이후에도 실행될 때 반드시 사용해야 한다
@autoclosure는 표현식을 자동으로 클로저로 변환해주는 키워드이다
@autoclosure는 주로 간단한 조건 검사나 지연 평가에서 사용된다
- 두 키워드를 함께 사용하는 경우도 있으며, 이때는
@escaping이 필요하다