[Swift 프로그래밍] 클로저(Closure)

이정훈·2022년 5월 30일
0

Swift 기본

목록 보기
11/22
post-thumbnail

본 내용은 스위프트 프로그래밍 3판 (야곰 지음) 교재를 공부한 내용을 바탕으로 작성 하였습니다.

클로저란?


클로저의 정의는 다음과 같다.

클로저: 어떠한 기능을 수행 할 수 있는 코드의 묶음

필자는 정의를 보자마자 뭔가 막막한 느낌이 들었는데 한가지 예시로 바로 느낌이 와닿았다.

정의에서 어떠한 기능을 수행하는이라는 문구를 자세히 생각해 보면 함수와 역할이 비슷하고 실제로 함수도 클로저의 일종이다. 또한 스위프트의 클로저는 다른 언어의 lambda와 비슷한 개념으로 볼 수 있다.

다음은 클로저가 가지는 특징이다.

  • 스위프트에서 클로저는 전달인자와 변수, 상수에 저장 및 전달이 가능하다.
  • 컴파일러가 클로저의 매개변수와 반환 값의 타입을 유추하여 매개변수와 반환 값의 타입을 명시하지 않아도 된다.
  • 클로저의 구현 코드가 한줄이라면 return 키워드를 생략해도 반환 값으로 인식한다.
  • 축약된 전달인자 이름 사용이 가능하다.
  • 후행 클로저를 사용 할 수 있다.

클로저가 가지는 특징을 보면 Swift는 함수형 프로그래밍 패러다임을 차용한 것을 다시 한번 확인할 수 있다.

클로저의 형태


기본적인 클로저의 형태는 다음과 같다.

{ (매개변수) -> (반환 타입) in
	(실행 코드)
}

다음은 상수에 클로저를 사용하여 구현한 코드이다.

let round: (Double, Double) -> Double = {(r: Double, PI: Double) in
    return 2 * PI * r   //클로저를 사용하여 상수 선언
}

let result: Double = round(2, 3.14)
print(result)

위에서 명시한 클로저의 특징으로 상수에 클로저를 사용하여 할당 할 수 있으며 상수 이름으로 매개 변수를 받아 마치 함수를 쓰는 것 처럼 활용이 가능하다.

이제 위에서 언급한 클로저의 특징들을 하나씩 알아보자

전달인자로의 클로저


위에서 언급한것과 같이 클로저를 전달인자로 전달하여 사용이 가능하다.

let circumference: (Double, Double) -> Double
circumference = {(r: Double, PI: Double) in return 2 * PI * r}

let area: (Double, Double) -> Double
area = {(r: Double, PI: Double) in return PI * r * r}

func circle(r: Double, PI: Double, method: (Double, Double) -> Double) -> Double {
    return method(r, PI)
}

var myCircle: Double
myCircle = circle(r: 3, PI: 3.14, method: circumference)
print(myCircle)

myCircle = circle(r: 3, PI: 3.14, method: area)
print(myCircle)

위의 코드는 circumference 상수에 원의 둘레를 구하는 클로저를 구현하였고, area 상수에는 원의 넓이를 구하는 클로저를 구현하였다.
그리고 circle 함수에는 원의 반지름과 PI의 값을 전달고 method 매개변수를 통해 원의 둘레를 구하는 클로저와 원의 넓이를 구하는 클로저를 전달인자로 전달 가능하도록 구현하였다.

후행 클로저


클로저의 기본 형태에서는 일반적인 매개변수를 전달 받고 클로저를 전달 받을 매개변수를 또 구현하여 형태가 복잡하다. 따라서 함수나 메서드의 마지막에 존재하는 클로저는 소괄호를 닫고 이후에 구현하는 후행 클로저 방식으로 구현이 가능하다.

func circle(r: Double, PI: Double, method: (Double, Double) -> Double) -> Double {
    return method(r, PI)
}

var yourCircle: Double
yourCircle = circle(r: 5, PI: 3.14) {(r: Double, PI: Double) -> Double in return 2 * PI * r}
print(yourCircle)

위와 같이 기본적인 매개변수들은 소괄호 안에 구현하고 클로저는 소괄호 이후에 구현하여 좀 더 가독성이 좋게 구현하였다.

여기서는 함수의 전달인자가 클로저 외에도 여러가지가 있지만 만약 전달인자가 클로저 뿐이라면 소괄호를 아에 생략하고 함수 뒤에 후행 클로저 형식으로 표현할 수도 있다.

반환 값 생략(타입 유추)


메서드의 매개변수로 클로저를 전달할때 매개변수에서 요구하는 형태의 클로저를 매개변수로 전달해야 한다. 이 말인 즉, 클로저의 매개변수와 반환 값은 메서드에 정의 되어 있는 매개변수의 타입과 반환 값의 타입을 보고 컴파일러가 유추가 가능하기 때문에 매개변수의 타입과 반환 값의 타입을 생략하여 구현이 가능하다.

func circle(r: Double, PI: Double, method: (Double, Double) -> Double) -> Double {
    return method(r, PI)
}

yourCircle = circle(r: 5,  PI: 3.14) {(r, PI) in return 2 * PI * r}
print(yourCircle)

단축 인자 이름


클로저에서 매개변수의 이름이 필요 없다면 매개변수 이름을 생략하고 구현이 가능하다. 다만 이럴경우 $0, $1, $2 ... 와 같이 순서대로 첫번째로 오는 전달인자, 두번째로 오는 전달인자.. 로 표현한다.

yourCircle = circle(r: 5, PI: 3.14, method: {
    return 2 * $0 * $1
})
print(yourCircle)

암시적 반환 표현


위에서 본 모든 코드들은 원의 둘레나 원의 넓이를 구하는 반환 값을 갖는다.
만약 클로가 반환 값을 가지고 내부 구현 코드가 한줄이라면 return 키워드를 생략하고 한 줄짜리 구현 코드를 반환 값으로 사용할 수 있다.

yourCircle = circle(r: 5, PI: 3.14) {
    2 * $0 * $1
}

print(yourCircle)
profile
새롭게 알게된 것을 기록하는 공간

0개의 댓글