반응형

Swift에는 "클로저(Closure)"라는 기능이 있다. 이것은 함수를 "값"으로 처리하는 구조이다. 이 클로저와 값으로 함수의 사용에 대해 설명한다.


함수는 "값"이다!

Swift 함수에는 매우 중요한 고유의 특성이 있다. 그것은 "값으로 취급"하는 것이다. 함수는 처리를 요약 한 것이지만, 이 함수 자체도 Swift에서는 "값"이다.

실제로 간단한 예제를 실행해 보자.

func calc(num:Int)->Int {
    var res = 0
    for n in 0...num {
        res += n
    }
    return res
}
 
var f1 = calc
 
print(f1(10))

위에 예제는 calc라는 함수를 정의하고 있다. 그리고 이 calc을 변수 f1에 대입한 다음에 이 변수 f1에 인수로 호출한다.

이제 제대로 calc의 처리가 실행되고 결과를 얻을 수 있다. 즉, 변수 f1에 calc 함수가 할당되어 제대로 작동하고 있다.

이 "함수는 값이다"라는 특징 덕분에, Swift에는 다양한 형태로 함수를 취급할 수 있다. 우선 이 "함수는 값"이라는 점을 확실히 기억하도록 하자.



클로저 (Closure)

이 "값으로써의 함수"의 기본을 알았으니, 이제 Swift의 중심 기능인 "클로저(Closure)"를 사용해 보기로하자.

클로저라고 하는 것은 "값으로써 함수를 인수로 지정하고 다른 함수에 전달하여 사용한다"는 방식이다. 함수는 값이기에 함수 자체를 인자로 지정한 함수도 만들 수 있다.

이렇게 함수의 처리 자체를 인수로 지정하고 다른 함수에 전달하는 기능이 클로저이다.

이는 실제로 보지 않으면 왠지 생소하게 느껴질 것이다. 아래에 간단한 사용 예제를 보도록 하자.

func calc(num:Int)->Int {
    var res = 0
    for n in 0...num {
        res += n
    }
    return res
}

func printResult(function:(num:Int)->Int, n:Int) {
    print(function(num: n))
}

printResult(calc, n: 123)

여기에서는 calc와 printResult라는 2개의 함수를 정의하고 있다. calc는 이전까지의 샘플과 동일하고 0부터 인수 값까지의 합을 계산하여 반환하는 예제이다. 클로저를 사용하는 함수는 printResult이다.

이 printResult에서는 함수와 Int 값을 인수로 전달된다. 함수의 형태는 (num:Int)->Int으로 지정되어 있다. 이것으로 calc 함수를 인수로 전달하여 호출하면 내부적으로 함수를 실행하고 결과가 출력되는 거다.

이 printResult은 단순히 "calc의 결과를 출력한다"는 것은 아니다. 인수 전달은 calc가 아니어도 상관없다. Int 값을 인수로 전달 Int 값을 반환하는 함수라면 무엇이든 전달해서 사용할 수 있다.

즉, 클로저를 사용하면 "처리를 외부로 분리할 수 있다"라는 장점이 있다. 이것이 클로저를 사용하는 큰 장점이다.




함수 리터럴

클로저를 사용할 때 함수를 값으로 전달해야 한다. 앞의 예제처럼 함수를 미리 정의 해두고, 그것을 인수로 지정해도 물론 가능하다.

하지만 너무 복잡한 처리가 아니라면, 그리고 한 곳에서만 사용하고, 다른 곳에서 쓸 수도 없다면 일부러 함수를 정의하는 것이 귀찮을 수도 있다.

이러한 경우 클로저를 사용한 함수를 사용할 때 함수를 인수로 그 곳에 직접 작성할 수도 있다. 이는 "함수 리터럴"형식으로 작성한다. 함수 리터럴의 작성은 매우 간단하다.

{... 처리 작성 ...}

이것뿐이다. 사실은 Swift에서는 {} 내에 처리를 작한 것은 모든 함수로 취급한다. 다만, 이것만을 인수의 값으로 전달할 수 없기 때문에, 실제로는 다음과 같이 쓰는 경우가 많을 것이다.

{인수 in ... 처리 작성 ...}

인수가 여러 개인 경우 쉼표로 구분하여 작성한다. 이와 같이 함수 리터럴을 사용하여 함수의 값을 직접 인수를 작성하면, 미리 필요한 함수를 정의해 두지 않아도 된다.

아래에 그 이용 예제를 보도록 하자.

func printResult(function:(num:Int)->Int, n:Int) {
    print(function(num: n))
}

printResult({n in n * 2}, n: 10)

printResult({n in
    var re:Int = 0
    for num in 0...n {
        re += num
    }
    return re
}, n: 100)

여기에서는 이전 printResult을 정의해서 그것을 호출 처리로 쓰고 있다. 보면 알 수 있듯이, calc 함수는 더 이상 사용하지 않는다. 그 대신에, printResult를 호출할 때 함수 리터럴로 처리를 직접 작성하고 있다.

함수 리터럴은 단순히 하나의 계산식만으로 결과를 얻을 수 있는 경우는 한줄에 함께 쓸 수 있다. in 후에 단지 간단한 식을 쓰는 것만으로 끝난다.

여러 행을 전달하는 처리가 되면 나름대로 복잡하게 되지만, 한줄의 함수 리터럴이라면 간단히 사용하기 쉽다는 것을 알 수 있다.

클로저와 함수 리터럴에 익숙해지지 않으면 왠지 어려울 것 보일 수도 있지만, "함수를 값으로 처리하는 구조다"라는 것만 기억한다면 그렇게 복잡한 것은 아니다. 실제로 샘플을 여러 번 수정해 가면서 실행해 보면 금방 익숙해 질 것이다.

반응형

'Swift' 카테고리의 다른 글

[Swift] 프로토콜 및 확장  (0) 2017.12.10
[Swift] 함수 리터럴 및 클로저  (0) 2017.12.10
[Switf] 구조체, 열거형, 튜플  (0) 2017.12.09
[Swift] 배열과 사전  (0) 2017.12.09
[Swift] 클래스 기본  (0) 2017.12.09
[Swift] 함수  (0) 2017.12.09

+ Recent posts