iOS/개념

[Swift] 클로저(Closure)란?

안경 쓴 귀니 2022. 4. 9. 18:23
반응형

 

클로저(Closure)란?

 

  1. 클로저는 두 가지로 이루어진 객체다. 하나는 내부 함수이며, 또 다른 하나는 내부 함수가 만들어진 주변 환경이다.
  2. 클로저는 외부 함수 내에서 내부 함수를 반환하고, 내부 함수가 외부 함수의 지역 변수나 상수를 참조할 때 만들어진다.
  3. 일회용 함수를 작성할 수 있는 구문이다. 익명(Anonymous) 함수라고도 하며 Objective-C 언어의 블록(Block), 자바 언어의 람다(Lambda), 파이썬 언어의 람다(Lambda)와 동일하다고 보면 된다.
    일회용 함수란, 한 번만 사용할 구문들의 집합이면서, 그 형식은 함수로 작성되어야 하는 제약조건이 있을 때 만들어 사용할 수 있는 함수이다.

요약하자면, 클로저란 내부 함수와 내부 함수에 영향을 미치는 주변 환경(Context)을 모두 포함한 객체이다.

 

스위프트에서 클로저라고 부르는 객체는 대부분 다음 세 가지 주중 하나에 해당된다.

  1. 전역 함수 - 이름이 있으며, 주변 환경에서 캡처할 어떤 값도 없는 클로저
  2. 중첩 함수 - 이름이 있으며 자신을 둘러싼 함수로부터 값을 캡처할 수 있는 클로저
  3. 클로저 표현식 - 이름이 없으며 주변 환경으로부터 값을 캡처할 수 있는 경량 문법으로 작성된 클로저

 

클로저 표현식

 

클로저 표현식은 일반 함수의 선언 형식에서 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: 문법편

 

클로저는 표현식이 정말 다양해서 어렵네요. 😅

반응형