-
Notifications
You must be signed in to change notification settings - Fork 0
Escaping Closure란?
Escaping closure
는 영어단어 의미 그대로 탈출 가능한 클로저를 말합니다.
클로저가 함수로부터 escape
한다는 것은 해당 함수의 인자로 클로저가 전달되지만 함수 반환된 이후 실행되는 것을 말합니다.
즉 함수의 인자가 함수의 영역을 탈출하여 함수 밖에서도 사용할 수 있다는 것입니다. 우리가 기존에 알고 있는 scope 개념이랑은 다릅니다.
함수 밖에서도 유효하게 변수를 사용하고 싶을 때 @escaping
을 사용합니다.
일반 로컬 변수(ex. Int, String etc..)가 함수 밖에서 살아있는 것은 전역 변수를 함수에 가져와서 값을 새로 주는 것과 다르지 않아보이지만 escape는 A함수가 마무리된 상태에서만 B함수를 실행할 수 있습니다.
- 함수가 해당 함수 내부에서만 사용되지 않고 다른 곳으로 저장하거나 참조하거나 파라미터로 넘길 수 있습니다.
- 함수에서의 escaping이란 함수 내부에서 사용해야할 것이 외부에서 참조되거나 파라미터로 넘겨지는 현상을 말합니다.
- 함수라는 것은 파라미터 또한 포함되는 개념입니다.
매개변수로 사용되는 클로저는 @noescape가 기본값이기 때문에 매개변수 이름의 콜론(:) 뒤에 @escaping을 명시해주어야 합니다.
예제
GET 방식으로 JSON 형식의 데이터를 받아올 때 Response 객체를 통해 받을 수 있습니다. 일반적으로 서버에 Request를 전송한 직후 반환되어버리는데 Response가 Request 결과를 기다리게 하는 형태로 함수를 작성하려면 @escaping 를 명시해주어야 합니다. 즉 completion handler는 함수가 반환되고 서버로부터 값을 가져온 상태에서 실행됩니다.
아래 코드를 살펴봅시다.
func makeRequest(
toURL url: URL,
withHttpMethod httpMethod: HttpMethod,
completion: @escaping (_ result: Results) -> Void) {
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
//code
}
//code
}
}
클로저는 함수의 파라미터로 넣을 수 있는데 함수가 끝나고 실행되는 클로저, 위처럼 비동기 작업을 실행하는 함수들은 completion handler
매개변수로 클로저를 전달 인자로 받습니다. 이 때 completion handler는 함수의 작업이 완료가 된 후 호출되는 것을 보장받습니다.
또한 @escaping으로 표기된 클로저는 외부 값을 참조할 때 self를 꼭 표기하여 참조하여야 합니다. 그 이유는 함수에서 탈출한 후에 closure가 어떤 객체를 참조하고 있었는지 기억하기 위해서 존재합니다.
위 Escaping Closure 특징을 참고하여 보시면 좋습니다.
- 클로저 저장 : 함수가 종료된 이후에 사용되는 경우 / 외부 글로벌 변수에 저장되는 경우
- 비동기 작업 : DispatchQueue 등을 사용하여 비동기 작업을 수행하는 경우, 함수가 종료된 이후에도 클로저를 메모리에 잡아두어 비동기 작업을 이어가게 합니다.