Closures - The Swift Programming Language (Swift 5.7)

탈출 클로저에 대하여 설명하시오.

Escaping Closure

클로저는 함수에 인수로 전달될 때 함수를 이스케이프한다고 말하지만 함수가 반환된 후에 호출됩니다. 클로저를 매개변수 중 하나로 사용하는 함수를 선언할 때 매개변수 유형 앞에 @escaping을 작성하여 클로저가 이스케이프할 수 있음을 나타낼 수 있습니다.

escaping 클로저는 매개변수로 받은 클로저가 함수 내부 스코프를 탈출해서 외부 쓰레드로 가는 것이다.

사용이유

ex) 서버에 이미지를 비동기적으로 요청하고 반환하는 함수에서 escaping 클로저를 사용하지 않으면 empty 데이터를 반환하고 이미지가 업데이트 되지 않을 수 있다. 즉, 함수 내부에서 클로저의 사용이 끝난다는 말이다.

네트워크 요청 작업이 있을 때 비동기적으로 이를 처리하고 Task가 끝난 후 동작하는 것을 CompletionHandler에 명령하는 것이다.

func requestData(with url: URL,
                     completion: @escaping (Result<Data,APIError>) -> Void) {
        session.dataTask(with: url) { data, response, error in
            guard error == nil else {
                completion(.failure(.unknownErrorOccured))
                return
            }
            
            guard let response = response as? HTTPURLResponse,
                  (200..<300).contains(response.statusCode) else {
                completion(.failure(.invalidURL))
                
                return
            }
            
            guard let verifiedData = data else {
                completion(.failure(.emptyData))
                
                return
            }
            
            completion(.success(verifiedData))
        }.resume()
    }

언제 Escaping 하나?

Example

매개변수로 불러온 클로저를 해당 함수에서 사용하는 것은 전혀 문제가 되지 않는다.

하지만 이 클로저를 저장하고 다른 곳에서 호출하려고 한다면 컴파일 에러가 발생한다. 이를 다른 곳에서 사용 가능하도록 만들기 위해선 @escaping 키워드를 사용해 탈출 클로저를 만든다.