스위프트의 클로저

개요


스위프트에서 함수형 프로그래밍적인 대표적인 요소 클로저에 대해 알아보겠다.




클로저


클로저는 일종의 코드블럭이다. 함수도 클로저의 일종이다.

클로저는 변수나 상수가 선언된 위치에서 값이 아닌 참조를 얻을 수 있다. 이를 클로징이라고 하며 클로저는 여기에서 기원했다.

클로저는 총 3가지 형태를 가지고 있는데

  • 이름이 있고 어떤값도 얻지 않는 전역함수의 형태
  • 이름이 있고 다른 함수 내부 값을 얻을 수 있는 중첩된 함수의 형태
  • 이름이 없고 축약 문법으로 표현된 형태

클로저의 표현 방법에는 기본 클로저 표현과 후행 클로저 표현이 있다. 이들을 축약할 수 있는 방법까지 알아보겠다.

클로저는 변수나 상수에 대입이 가능하며, 함수의 파라메터로 전달될 때 많이 사용된다.

하나의 코드블럭이기에 함수를 사용할 때처럼 뒤에 ()를 붙여서 그냥 실행할 수 있다.




클로저 사용법


1
2
3
{ (매개변수) -> 반환형 in
    실행코드
}

클로저는 위와 같은 형태로 사용한다.

기본클로저와 후행클로저의 차이는 클로저의 위치 차이이다. 마지막 파라메터일 때 소괄호 생략하고 좀더 간결하게 적는 방법 같다.

함수라고 생각하고 보면 이해에 도움이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// (String, Int) -> Void 형의 상수
let closureExample = { (name: String, age: Int) -> Void in
    print(name, age)
}

//매개변수로의 클로저
func closureExample2 (exClosure: (String, Int) -> Void) {
    exClosure("kyujin", 25)
}
closureExample2 (exClosure: {name: String, age: Int) -> Void in
    print(name, age)
})

// 리턴형이 있는 클로저
let closureExample3 = { (name: String, age: Int) -> String in
    return "이름은 \(name) 나이는 \(age)"
}

//옵셔널 클로저
func closureExample4 (exClosure: ((String, Int) -> Void))? = nil {
    exClosure?("kyujin", 25)
}
closureExample2 (exClosure: {name: String, age: Int) -> Void in
    print(name, age)
})




클로저의 축약


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 기본 클로저 형태
let closureEx: String = { (name: String, age: Int) -> String in
    return "이름은 \(name) 나이는 \(age)"
}

// 매개변수의 자료형 생략 가능
let closureEx: String = { (name, age) -> String in
    return "이름은 \(name) 나이는 \(age)"
}

// 반환형 생략 가능
let closureEx: String = { (name, age) in
    return "이름은 \(name) 나이는 \(age)"
}

// 매개변수 생략 가능
let closureEx: String = { 
    return "이름은 \($0) 나이는 \($1)"
}

// 반환 키워드 생략 가능
let closureEx: String = { "이름은 \($0) 나이는 \($1)" }

// 후행 클로저
func closureExample2 (exClosure: (String, Int) -> Void) {
    exClosure("kyujin", 25)
}
closureExample2 {print($0, $1)}




탈출클로저


함수의 파라메터로 전달한 클로저가 함수 종료 후에 호출될 때 클로저가 함수를 탈출한다고 표현한다.

매개변수 적기전 :다음 @escaping을 적으면 함수가 끝나도 해당 클로저를 호출할 수 있다고 하는 것이다.

만약 일반적인 클로저로 전달한 애를 탈출 클로저인척 해야하는 경우 withoutActuallyEscaping(_:do:)를 이용하면 된다.




자동클로저


함수의 전달인자로 전달하는 클로저가 아닌 표현을 자동으로 클로저로 변환해주는 클로저를 자동클로저라고 한다.

자동클로저는 매개변수를 가지지 않는다.

탈출클로저와 같이 @autoclosure를 적으면 된다.




클로저의 사용


아직은 눈에 잘 안익는다.

잘 활용한다면 매우 좋은 기능이지만 독이 될 수도 있을 것 같다.