Swift - 자동 클로저(Auto Closure)

이재원·2024년 8월 25일
0

Swift

목록 보기
11/13
post-thumbnail
post-custom-banner

자동 클로저(Auto closure)

자동 클로저는 말 그대로, 특정 표현식을 함수의 매개변수로 전달할 때 그 표현식을 클로저로 자동으로 감싸주는 기능이에요. 쉽게 말해, 복잡하게 중괄호({ })로 감싸주지 않아도 스위프트가 알아서 클로저로 만들어 준다는 거죠.

자동 클로저는 인수를 따로 받지 않고, 호출될 때 내부에 있는 표현식의 결과를 반환해 줍니다.

자동 클로저의 특징

지연 평가

자동 클로저의 진짜 매력은 지연 평가예요. 코드가 바로 실행되지 않고, 클로저가 호출될 때만 실행된다는 거죠. 이렇게 하면 코드 실행 시기를 우리가 제어할 수 있어서, 사이드 이펙트가 있거나 계산이 오래 걸리는 경우에 딱 좋아요.

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"

print("Now serving \\(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

위 코드에서 볼 수 있듯이, customerProvider는 클로저로 배열의 첫 번째 요소를 삭제하는 코드를 담고 있지만, 이 클로저가 호출되기 전까지는 배열이 그대로 유지됩니다. 호출 전까지는 아무 일도 일어나지 않아요. 덕분에 클로저를 호출하지 않으면, 배열의 요소는 삭제되지 않고 그대로 남아있죠.

그래서 customerProvider의 타입은 String이 아니라 () -> String 타입이에요. 호출하기 전까지는 그저 함수처럼 보관만 되는 거죠.

명시적 클로저 작성 불필요

자동 클로저를 사용할 때는 클로저를 명시적으로 작성할 필요가 없어요. 그냥 표현식만 전달하면, 스위프트가 알아서 클로저로 변환해 줍니다.

이렇게 하면 지연 평가 덕분에 코드가 실행되는 시점을 우리가 컨트롤할 수 있죠.

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \\(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) })
// Prints "Now serving Alex!"

여기서 @autoclosure를 추가해 주면, 중괄호도 생략할 수 있어요.

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \\(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"

탈출 클로저와 자동 클로저를 함께 사용

자동 클로저와 탈출 클로저를 함께 사용하려면, @autoclosure@escaping을 둘 다 붙여주면 돼요.

// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \\(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \\(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

여기서는 @escaping 덕분에, 클로저가 함수의 실행이 끝난 후에도 살아남아, 나중에 호출할 수 있게 되는 거죠. 덕분에 클로저를 저장해두고 나중에 호출할 수 있어요.

요약

  • 자동 클로저(Auto Closure): 특정 표현식을 함수의 매개변수로 전달할 때, 해당 표현식을 클로저로 자동으로 감싸줌.
  • 지연 평가(Lazy Evaluation): 자동 클로저는 호출될 때만 실행되며, 실행 시점을 제어할 수 있어 계산이 오래 걸리거나 부작용이 있는 코드에 유용.
  • 명시적 클로저 작성 불필요: 자동 클로저를 사용하면 클로저를 명시적으로 작성할 필요 없이, 표현식만 전달하면 됨.
  • @autoclosure 키워드: 이 키워드를 사용하면 중괄호를 생략할 수 있음.
  • 탈출 클로저와의 조합: @escaping과 함께 사용하면, 자동 클로저를 나중에 호출할 수 있도록 저장 가능.

출처
https://bbiguduk.gitbook.io/swift/language-guide-1/closures#autoclosures

profile
20학번 새내기^^(였음..)
post-custom-banner

0개의 댓글