클로저(Closure)란?
- 클로저는 두 가지로 이루어진 객체다. 하나는 내부 함수이며, 또 다른 하나는 내부 함수가 만들어진 주변 환경이다.
- 클로저는 외부 함수 내에서 내부 함수를 반환하고, 내부 함수가 외부 함수의 지역 변수나 상수를 참조할 때 만들어진다.
- 일회용 함수를 작성할 수 있는 구문이다. 익명(Anonymous) 함수라고도 하며 Objective-C 언어의 블록(Block), 자바 언어의 람다(Lambda), 파이썬 언어의 람다(Lambda)와 동일하다고 보면 된다.
일회용 함수란, 한 번만 사용할 구문들의 집합이면서, 그 형식은 함수로 작성되어야 하는 제약조건이 있을 때 만들어 사용할 수 있는 함수이다.
요약하자면, 클로저란 내부 함수와 내부 함수에 영향을 미치는 주변 환경(Context)을 모두 포함한 객체이다.
스위프트에서 클로저라고 부르는 객체는 대부분 다음 세 가지 주중 하나에 해당된다.
- 전역 함수 - 이름이 있으며, 주변 환경에서 캡처할 어떤 값도 없는 클로저
- 중첩 함수 - 이름이 있으며 자신을 둘러싼 함수로부터 값을 캡처할 수 있는 클로저
- 클로저 표현식 - 이름이 없으며 주변 환경으로부터 값을 캡처할 수 있는 경량 문법으로 작성된 클로저
클로저 표현식
클로저 표현식은 일반 함수의 선언 형식에서 func 키워드와 함수명을 제외한 나머지 부분만 작성한 경량 문법을 사용한다.
{ (매개변수) -> 반환 타입 in
실행할 구문
}
ex.
{ () -> () in
print("클로저 실행")
}
반환값이 없을 때는 일반 함수처럼 반환 값 타입을 생략하는 것이 아니라, 함수 타입을 표현하는 것처럼 빈 괄호를 사용하여 반환 값이 없음을 명시적으로 표현해야 한다.
이는 클로저 표현식의 모호성을 제거하기 위한 규칙이다.
빈 괄호 대신 타입 알리어스로 작성된 문자열 Void를 사용해도 된다.
작성된 클로저 표현식은 그 자체로 함수라고 할 수 있다.
클로저 표현식은 대부분 인자 값으로 함수를 넘겨주어야 할 때 사용하지만, 직접 실행해볼 수도 있다.
이를 위한 두 가지 방법이 제공된다.
1. 일급 함수로서의 특성을 활용하여 상수나 변수에 클로저 표현식을 할당한 다음 실행하는 방법
let f = { () -> Void in
print("클로저 실행")
}
f()
2. 클로저를 직접 실행하는 방법
({ () -> Void in
print("클로저 실행")
}()
추가) 매개변수가 있는 형태의 클로저 표현식
let c = { (s1: Int, s2: String) -> Void in
print("s1: \(s1), s2:\(s2)")
}
c(1, "closure")
아래와 같이 order 함수가 있다.
var value = [1, 9, 5, 7, 3, 2]
func order(s1: Int, s2: Int) -> Bool {
if s1 > s2 {
return true
} else {
return false
}
}
value.sort(by: order)
value.sort(by: order(s1:s2:))
위 order 함수를 클로저 표현식으로 바꾸면 아래와 같다.
{ (s1: Int, s2: Int) -> Bool in
if s1 > s2 {
return true
} else {
return false
}
}
위 클로저를 sort 메서드의 인자 값으로 바로 사용하면 아래와 같다.
value.sort(by: {
(s1: Int, s2: Int) -> Bool in
if s1 > s2 {{
return true
} else {
return false
}
})
위 클로저를 간단하게 요약하면 아래와 같다.
1. 조건문 요약
{ (s1: Int, s2: Int) -> Bool in
return s1 > s2
}
2. 더 간단하게 한 줄로 요약
value.sort(by: {(s1: Int, s2: Int) -> Bool in return s1 > s2 })
클로저 표현식 자체를 간결하게 줄여보기
1. 반환 값의 타입을 생략
반환 타입을 생략하면 컴파일러는 클로저 표현식의 구문을 해석하여 반환 값을 찾고, 이 값의 타입을 추론하여 클로저의 반환 타입을 정의한다.
{ (s1: Int, s2: Int) in
return s1 > s2
}
위 클로저를 sort 메서드의 인자 값으로 사용하면 아래와 같다.
value.sort(by: (s1: Int, s2: Int) in return s1 > s2 })
2. 매개변수의 타입 정의를 생략
매개변수의 컴파일러가 실제로 대입되는 값을 기반으로 추론하기 때문에 생략이 가능하다.
{ s1, s2 in return s1 > s2 }
매개변수의 타입 어노테이션이 생략되면서 매개변수를 감싸고 있던 괄호도 함께 생략된다.
위 클로저를 sort 메서드의 인자 값으로 사용하면 아래와 같다.
value.sort(by: { s1, s2 in return s1 > s2 })
키워드 in을 기준으로 하여 매개변수 정의와 실행 구문으로 나뉜다.
매개변수 in 실행 구문
3. 매개변수 생략
매개변수가 생략되면 매개변수명 대신 $0, $1, $2.. 와 같은 이름으로 할당된 내부 상수를 이용할 수 있다.
입력받은 인자 값의 순서대로 매칭 된다. (즉 s1 대신 $0, s2 대신 $2이 사용됨)
매개변수가 생략되면 남는 건 실행 구문이다.
{ return $0 > $1 }
위 클로저를 sort 메서드의 인자 값으로 사용하면 아래와 같다.
value.sort(by: return $0 > $1 })
4. 연산자 함수 (Operator Functions)
클로저 표현식보다 더 간결하게 표현할 수 있는 연산자 함수
연산자만을 사용하여 의미하는 바를 정확히 나타낼 수 있을 때 사용한다.
value.sort(by: > )
출처: 꼼꼼한 재은씨의 Swift: 문법편
클로저는 표현식이 정말 다양해서 어렵네요. 😅
'iOS > 개념' 카테고리의 다른 글
[Swift] 스위프트 변수와 상수 (0) | 2022.04.02 |
---|---|
[Swift] 스위프트 문법 특성 (0) | 2022.04.01 |
[Swift] 함수 타입이란? (Function Types) (0) | 2022.03.19 |
[Swift] 프로퍼티 (Properties) 종류 (저장 or 연산 or 타입) (0) | 2022.03.08 |
[Swift] SwiftUI Stack (VStack, HStack, ZStack) (0) | 2022.02.23 |