7.4.3 트레일링 클로저(Trailing Closure)

트레일링 클로저는 함수의 마지막 인자값이 클로저일 때, 이를 인자값 형식으로 작성하는 대신 함수의 뒤에 꼬리처럼 붙일 수 있는 문법을 의미합니다. 이때 인자 레이블은 생략됩니다. 주의할 점은 이 문법이 함수의 마지막 인자값에만 적용된다는 것입니다. 만약 인자값이 하나라면 이는 첫번째 인자값이지만 동시에 마지막 인자값이므로 트레일링 클로저 문법을 사용할 수 있습니다.

value.sort() { (s1, s2) in
    reutnr s1 > s2
}

자세히 살펴 보면 인자값으로 사용되던 클로저가 통째로 바깥으로 빼내어진 다음, sort() 메서드의 뒤쪽에 달라붙은 것을 알 수 있습니다. 이로 인해 얻는 장점은 코딩 과정에서 sort() 함수를 열고 닫는 범위가 줄어든다는 것입니다. 인자값이 하나일 경우 트레일링 클로저 문법은 조금 더 변화할 여지가 있습니다.

value.sort { (s1, s2) in
    reutnr s1 > s2
}

이번에는 sort 메서드 뒤의 괄호가 아예 사라졌습니다. 더 필요한 인자값도 없고, 트레일링 클로저 문법 덕분에 호출 구문이라는 점을 명확히 할 수 있어서 굳이 괄호의 필요성이 없기 때문입니다. 만약 인자값이 여러 개라면 무작정 괄호를 생략해서는 안됩니다.

func divide(base: Int, success s: () -> Void) -> Int {
    defer {
        s() // 성공 함수를 실행한다
    }
    return 100 / base
}

앞서 사용했던 divide 함수의 변형입니다. 두 개의 인자값을 받는데 마지막 인자값에 클로저를 넣을 수 있으므로 위 함수는 트레일링 클로저를 사용할 수 있는 조건이 충족됩니다. 호출하는 구문은 다음과 같습니다.

divide(base: 100) { () in 
    print("연산이 성공했습니다")
}

만약 두 개의 클로저 인자값이 사용될 경우 트레일링 클로저도 연이어 적용할 수 있을지 생각할지 모르지만, 불가능합니다. 예제를 보겠습니다.

func divide(base: Int, success s: () -> Void, fail f: () -> Void) -> Int {
    guard base != 0 else {
        f() // 실패 함수를 실행한다
        return 0
    }
    
    defer {
        s() // 성공 함수를 실행한다
    }
    return 100 / base
}

호출하는 구문을 보겠습니다.

divide(base: 100, success: { () in 
    print("연산이 성공했습니다"))
}) { () in 
    print("연산이 성공했습니다")
}

이렇게 success는 마지막 인자값이 아니므로 트레일링 클로저로 사용할 수 없습니다.

Last updated