이 포스트는 야곰님의 Swift 프로그래밍 2판을 보고 스스로 공부한 내용을 정리한 포스트 입니다.


예제 코드.


참고 자료.


자동 클로저(Auto Closure).

  • 함수의 전달인자(Argument)로 전달하는 표현을 자동으로 변환해주는 클로저를 '자동 클로저(Auto Closure)'라고 한다.

    • 자동 클로저는 전달인자를 갖지 않는다.
  • 자동 클로저는 호출되었을 때 자신이 감싸고 있는 코드의 결괏값을 반환한다.

  • 자동 클로저는 함수로 전달하는 클로저를 (소괄호와 중괄호를 겹쳐 써야 하는) 어려운 클로저 문법을 사용하지 않고도 클로저로 사용할 수 있도록 문법적 편의를 제공한다.

  • 스위프트 표준 라이브러리에는 자동 클로저를 호출하는 함수가 구현되어 있어 이를 사용하는 일이 종종있다.

  • 하지만 직접 자동 클로저를 호출하는 함수를 구현하는 일은 흔치 않을 것이다.

    • 예를 들어 스위프트 표준 라이브러리에 구현되어 있는 assert(condition:message:file:line:) 함수는 condition과 message 매개변수가 자동 클로저이다.

    • condition 매개변수는 디버그용 빌드에서만 실행되고, message 매개변수는 condition 매개변수가 false일 때만 실행된다.

  • 자동 클로저는 클로저가 호출되기 전 까지 클로저 내부의 코드가 동작하지 않는다.

    • 따라서 연산을 지연시킬 수 있다.

    • 이 과정은 연산에 자원을 많이 소모한다거나 부작용이 우려될 때 유용하게 사용할 수 있다.

      • 그 이유는 코드의 실행을 제어하기 좋기 때문이다.

클로저를 이용한 연산 지연.

autoClosureImage-1

  • 위의 코드를 통하여 클로저가 연산을 어떻게 지연시킬 수 있는지 확인 할 수 있다.

  • 위의 코드에서 customerProvider 상수에 저장해둔 클로저는 하나의 명령문 묶음으로 볼 수 있다.

    • Array의 removeFirst() 메서드는 자신의 첫 번째 요소를 제거하면서 그 요소를 반환해주는 메서드이다.
  • 그래서 customerProvider()를 선언했지만 바로 아래서 호출한 print(customerInLine.count)에서는 클로저 내부의 연산이 반영되지 않으며 클로저가 실제로 실행되기 전까지는 removeFirst() 메서드의 연산을 실행하지도 않는다.

  • 그 뒤에 실제로 클로저를 실행하게 되면 그때서야 연산을 실행하게 된다.

  • 클로저가 영영 호출되지 않는다면 내부의 코드도 실행되지 않기 때문에 해당 연산을 실행되지 않는다.


함수의 전달인자로 전달하는 클로저.

autoClosureImage-2

  • 위의 코드는 함수의 전달인자로 직접 클로저를 작성하여 전달해주었다.

  • 코드의 serveCustomer(_:) 함수는 클로저를 매개변수로 전달받고 있다.


NOTE. 암시적 반환 표현.

  • ‘함수의 전달인자로 전달하는 클로저’의 코드에서 ‘클로저를 이용한 연산 지연’ 코드와는 다르게 클로저 내부에서 return 키워드를 사용하지 않아도 되는 이유는 암시적 반환 표현 때문이다.

  • 물론, ‘클로저를 이용한 연산 지연’ 코드에서도 return 키워드를 생략해줘도 된다.

  • 반대로 ‘함수의 전달인자로 전달하는 클로저’의 코드에서도 return 키워드를 명확하게 반환 값임을 명시해줄 수도 있다.


자동 클로저의 사용.

autoClosureImage-3

  • 위의 코드는 기존의 serveCustomer(_:) 함수와 동일한 역활을 하지만 매개변수에 @autoclosure 속성을 주었기 때문에 자동 클로저 기능을 사용한다.

  • 자동 클로저 속성을 부여한 매개변수는 클로저 대신에 customerInLine.removeFirst() 코드의 실행 결과인 String 타입의 문자열을 전달인자로 받게 된다.

  • String 타입의 값이 자동 클로저 매개변수에 전달되면 String 값을 매개변수가 없는 String 값을 반환하는 클로저로 변환해준다.

  • String 타입의 값을 전달 받는 이유는 자동 클로저의 반환 타입이 String이기 때문이다.

  • 자동 클로저는 전달인자를 갖지 않기 때문에 반환 타입의 값이 자동 클로저의 매개변수로 전달되면 이를 클로저로 바꿔줄 수 있는 것이다.

  • 이렇게 String 값으로 전달된 전달인자가 자동으로 클로저로 변환되기 때문에 자동 클로저라고 부른다.

  • 자동 클로저를 사용하면 기존의 사용 방법처럼 클로저를 전달인자로 넘겨줄 수 없다.


자동 클로저의 탈출.

autoClosureImage-4

  • 기본적으로 @autoclosure 속성은 @noescape 속성을 포함한다.

    • 즉, @autoclosure 속성을 사용하면 @noescape 속성도 부여됨을 암시하는 것이다.
  • 만약 자동 클로저를 탈출하는 클로저로 사용하고 싶다면 @autoclosure 속성 뒤에 @escaping 속성을 덧붙여서 위의 코드처럼 사용하면 된다.

  • 위의 코드를 살펴보면 탈출 가능한 자동 클로저를 매개변수로 받아서 반환 값으로 반환하는 returnProvider(_:) 함수가 있다.

    • 이 함수의 전달인자로 전달한 후 클로저로 변환된 코드들이 그대로 클로저의 형태로 반환되는 것을 알 수 있다.

    • 즉, 함수를 탈출하는 클로저가 되는 것이다. 그래서 위의 코드와 같이 @autoclosure @escaping 속성을 사용해야 한다.


클로저 파트의 마무리.

  • 클로저는 스위프트의 막강한 기능에 매번 함께하는 파트너가 될 것이다.

  • 클로저는 생략할 수 있는 부분이 많다. 그렇기 때문에 경우의 수만 따져보더라도 정말 다양한 표현의 클로저가 만들어질 수 있다.

    • 타입 유추만 사용할 수도 있고, 암시적 반환 표현만 사용할 수 있으며, 단축 인자 이름만 사용할 수도 있고, 이를 모두 사용할 수도, 사용하지 않을 수도 있다.

    • 그렇기 때문에 다양한 클로저 표현 방법을 알아두고, 잘 활용할 줄 아는 지혜가 필요하다. 물론 다른 사람의 코드를 이해하려면 이를 모두 알고 있어야 함은 물론이다.

  • 클로저의 축약 표현들이 득이 될 수도, 독이 될 수도 있을 것이다.