[Swift] 클로저의 기본

Uno·2021년 4월 26일
0

Tip-Swift

목록 보기
1/26

클로저 기본기


클로저가 클로저인 이뉴는 “close over” 입니다. 클로버 범위 내에서 변수와 상수를 “닫을” 수 있다는 뜻이죠. 닫는다? 뭘 닫는다는 걸까요?

저는 “닫을” 을 “연산할 수” 혹은 “해결할 수” 라고 이해했습니다.
그러니까 클로저 범위 내에서 변수와 상수를 연산을 할 수 있다. 해결을 할 수 있다. 로 인지하고 있습니다.

용어 하나를 설명하자면,
“클로저 범위에 상수와 변수가 들어왔다.” == “캡쳐되었다.” 라고 합니다.

클로저에 대한 또 다른 이해는 “이름 없는 함수” 입니다. 함수의 역할을 하지만 함수의 이름이 없습니다. 이걸 왜 이용하는 걸까요?
제 생각은 코드량을 줄여주고, 코드의 로직을 바로 볼 수 있다는 장점에 사용하는 것이라고 봅니다.
( 다른 이유로는 다른 사람의 코드를 읽기위해서 )

간단하게 클로저를 정의하겠습니다.

var multiplyClosure: (Int, Int) -> Int

multiplyClosure 이 친구는 두 개의 Int 값을 받고 Int를 리턴하고 있습니다.

플레이그라운드에서 실행하기 위해서는 다음과 같이 정의해주어야 합니다.

var multiplayClosure = { (a: Int, b: Int) -> Int in
	return a * b
}

a와 b 라는 값을 받습니다. 타입은 Int 입니다. 리턴값으로 Int를 리턴합니다. 이전과 다르게 “in” 이라는 친구가 생겼죠. 위 코드를 구어적 표현으로 하자면 다음과 같습니다.

"multiplayClosure" 를 정의할께. 근데 값은 a와 b를 받고 리턴은 Int로 해. 아 맞다 a와 b도 Int야. 근데 리턴을 어떻게 처리할 거냐고? 그건 'in' 내부 를 보면 된단다.

이제 클로저를 사용해보겠습니다.

let result = multiplayClosure(4, 2)
// result: 8

축약 문법


xcode를 통해서 Definition을 보신 경험이 있다면, (기본 라이브러리든 다른사람의 코드든) $ 을 본 경우가 있을 겁니다. 저도 처음봤을 때, 뭔가 했던 기억이 있네요. 그런 것들은 swift에서 약속된 “대명사” 같은 것들 입니다. 이것에 대해서 설명드릴께요.

먼저 기본형에서 “return”을 생략한 경우입니다.

multiplayClosure = { (a: Int, b: Int) -> Int in
	a * b
}

return 만 사라졌죠. 그래도 한 줄일 경우 return이라고 추론을 통해 자동으로 처리해줍니다.(누가? swift)

좀 더 축약을 해볼게요.

multiplayClosure = { (a, b) in
	a * b
}

a와 b를 받아서 a*b로 리턴한다. 여전히 코드의 로직은 이전과 동일합니다. 다만 Type 들이 사라졌죠. swift에서 타입 추론을 적극적으로 활용했다고 볼 수 있겠습니다.

이제 극한으로 가봅니다.

multiplayClosure = {
	$0 * $1
}

초반부에 말씀드린 “$”가 나왔습니다. 앞으로 $를 보면 인자를 뜻하는 구나.. 라고 생각하시면 됩니다.
0번째 인자와 1번째 인자를 받겠구나, 그리고 그 둘을 곱해서 리턴하는구나. 라고 이해하시면 됩니다. 처음 보면 익숙치 않아서 그런 것 뿐이지 귀납적으로 경험이 쌓이다보면 역으로 이해되는 부분이니 눈 도장 찍고 넘어가시면 됩니다.

지금까지 배운 것들에 복잡성을 한 술 추가해보겠습니다.

func operateOnNumbers(_ a: Int, _ b: Int,
						  operation: (Int, Int) -> Int) -> Int {
	let result = opertaion(a, b)
	print(result)
	return result
}

“oprateOnNumbers” 메소드는 인자로 3 가지를 받네요.
a, b, operation
a와 b는 직관적으로 Int입을 알 수 있는데, operation은 뭐지? 라고 하실 수 있습니다. 어려울수록 쪼개서 보면 쉽습니다.
(Int, Int) -> Int
Int 값 두 개를 받아서 Int를 리턴하는 것을 ‘인자’ 로 받는구나…

함수 전체는 Int로 리턴합니다.
오케이. 그러면 한번 사용해보죠.

let addClosure = { (a: Int, b: Int) in
	a + b
}
opertaeOnNumbers(4, 2, operation: addClosure)

4 == a
2 == b
operation == addClosure
모두 type이 일치하므로 정상적으로 동작합니다.

아까 클로저는 이름이 없는 함수라고 했죠. 그래서 이렇게 작성해도 동일합니다.

func addFunction(_ a: Int, _ b: Int) -> Int {
	a + b
}
opertaeOnNumbers(4, 2, addFunction)

위 예시는 클로저 아래 예시는 메소드 입니다.

이제 코드에 축약을 계속 해보겠습니다,

opertaeOnNumbers(4, 2, opertaion: { (a: Int, b: Int) -> Int in
	return a + b
})
operateOnNUmbers(4, 2, opertaion: +)
operateOnNumbers(4, 2, opertaion: { $0 + $1 }
operateOnNumbers(4, 2) {
  $0 + $1
}

이렇게 축약하는 것의 명칭은 “trailing closure syntax.” 라고 합니다. ( 다른 개발자와 소통하기 위해 명칭을 꼭 알아두는 것이 좋더라구요.)

클로저는 어찌보면 도움을 주는 기술입니다. 본질적으로는 "함수"라고 퉁치고 이해하셔도 될 겁니다. 다만, 정량적으로 코드를 많이 작성하게 될 때, 좀 더 코드를 간결하고 줄일 수 있는 방법을 찾을 때, 그런 상황에서 "클로저"를 떠올리시면 실전에서 도움이 되지 않을까 조심스레 조언해봅니다.

참고자료

https://www.raywenderlich.com/books/swift-apprentice/v6.0/chapters/8-collection-iteration-with-closures#toc-chapter-012-anchor-001

profile
iOS & Flutter

0개의 댓글