Search
Duplicate

Closure (클로저) - 개념

생성일
2023/08/04 14:22
태그
Grammar

Closure (클로저)

 클로저란?

클로저라고 하면 보틍 익명함수를 뜻한다고 생각하는 사람이 많을 것이다.
하지만 사실 func 키워드를 이용해 이름을 붙여주는 함수들도 모두 클로저이다!
즉, 클로저는 함수를 변수의 형태로 바꾼 것이다! (클로저는 함수)
클로저는 다음과 같이 두 가지의 종류가 있다.
Named Closure
Unnamed Closure
ex) Named Closure
func doSomething() { print("Somaker") }
Swift
복사
→ Named Closure는 클로저라고 부르지 않고, 그냥 함수라고 부른다.
→ 하지만 클로저란 사실은 변함 없다.
ex) Unnamed Closure
let closure = { print("Somaker") }
Swift
복사
익명함수, 즉 Unnamed Closure 라고 부른다.
→ 보통 Closure라고 하면, Unnamed Closure 를 말한다.

 요약

클로저는 Named Closure & Unnamed Closure 둘 다 포함하지만, 보통 Unnamed Closure를 말한다.
클로저도 익명이긴 하지만 함수이기 때문에, 1급 객체 함수의 특성을 그대로 다 가지고 있다. 그래서 클로저 또한 자료형을 가지고 있다!

 클로저 표현식

 클로저 표현식

{ (Parameters) -> Return Type in // Closure Head 실행구문 // Closure Body }
Swift
복사
→ 익명 함수인 만큼 fun 이란 키워드를 쓰지 않는다.
클로저는 Closure HeadClosure Body 로 이루어져 있는데
이 둘을 구분지어주는 게 바로 in 키워드 이다.

 파라미터와 리턴타입 둘 다 없는 클로저

클로저는 익명이긴 하지만 함수이다!
따라서 Swift에서 1급 객체이기 때문에, 다음과 같이 상수에 클로저를 대입할 수 있다.
특히 Parameter와 Return Type 둘 다 없는 경우는 다음과 같이 사용한다.
let closure = { () -> () in print("Closure") }
Swift
복사
그러면 함수처럼 Return Type 없으면 생략 가능할까? Yes!
심지어 Return Type이 있어도 생략이 가능하다. 함수에서 안되는 Parameter 조차 생략이 가능하다.

 파라미터와 리턴타입이 있는 클로저

let closure = { (name: String) -> String in return "Hello, \(name)" }
Swift
복사
주의할 점은
‘함수 때 배운대로 파라미터의 “name”은 단독으로 쓰였으니, Argument Label이자, Parameter Name 인가?’
라고 생각할 수 있지만
클로저에서는 Argument Label을 사용하지 않는다.
따라서, name은 Argument Label 이 아니고, 오직 Parameter Name 이다! 그래서 다음과 같이 클로저를 호출할 때
closure("HJ") // (O) closure(name: "HJ") // Error!
Swift
복사
Argument Label을 사용하지 않는다.

 1급 객체로서 클로저

1.
클로저를 변수나 상수에 대입할 수 있다.
클로저 또한 변수나 상수에 대입할 수 있고, 이 대입된 변수나 상수로 실행도 할 수 있다.
let closure = { () -> () in print("Closure") }
Swift
복사
이런 식으로 대입과 동시에 클로저를 작성할 수도 있고, 또는 기존에 클로저를 대입한 변수나 상수를
let closure2 = closure
Swift
복사
이렇게 새로운 변수나 상수에 대입할 수도 있다!
2.
함수의 파라미터 타입으로 클로저를 전달할 수 있다.
func doSomething(closure: () -> ()) { closure() }
Swift
복사
함수를 파라미터로 전달받는 doSomething이라는 함수가 있다.
이 경우, 파라미터로 함수를 넘겨줘도 되지만
doSomething(closure: { () -> () in print("Hello") })
Swift
복사
이렇게 클로저를 넘겨줘도 된다!
3.
함수의 반환 타입으로 클로저를 사용할 수 있다.
이 또한, 선언부는 기존 함수와 똑같지만,
func doSomething() -> () -> () { }
Swift
복사
이렇게!, 그러나 실제 값을 return 할 때 함수가 아닌
func doSomething() -> () -> () { return { () -> () in print("Hello HJ") } }
Swift
복사
이렇게 클로저를 리턴할 수도 있다!
또한 호출하는 곳에서 클로저를 받아서 다음과 같이
let closure = doSomething() closure()
Swift
복사
실행시킬 수도 있다!

 클로저 실행하기

클로저를 실행할 수 있는 방법은 크게 두 가지가 있는데

 1. 클로저가 대입된 변수나 상수로 호출하기

let closure = { () -> String in return "Hello HJ" } closure()
Swift
복사
이런 식으로 클로저가 대입된 상수 closure를 호출 구문인 () 를 이용해서 실행시킬 수 있다.

 2. 클로저 직접 실행하기

클로저를 변수나 상수에 대입하지 않고 실행시키고 싶다면 (완벽한 일회성), 그 땐 클로저를 () 소괄호로 감싸고, 마지막에 호출 구문인 () 를 추가해주면 된다.
({ () -> () in print("Hello HJ") })()
Swift
복사
클로저 사용법은 너무 길고 헷갈린다. 따라서 Swift는 클로저 경량 문법이라는 것을 지원한다! (2편!)

 Reference