클로저 그게 뭔데요?
swift.org에 따르면 클로저는 이름없는 함수(코드 블록)을 말합니다. C 및 Objective-C의 블록과 JAVA의 람다와 유사하다고 하네요!
클로저는 상수나 변수의 참조를 캡쳐(capture)해 저장할 수 있습니다.
클로저를 사용하는 이유
한마디로 말씀드리자면 코드를 굉장히 간결하게 작성할 수 있어요!
집게리아에서 주문(order)를 받아 처리한 결과를 문자열로 반환하는 동작인데요,
let orderProcessing: (String) -> String = { order in
return "주문하신 \(order)를 만들었습니다."
}
print(orderProcessing("크랩버거"))
동일한 기능을 수행하는 함수:
func orderProcessing(order: String) -> String {
return "주문하신 \(order)를 만들었습니다."
}
print(orderProcessing(order: "크랩버거"))
클로저를 사용하면 함수를 정의하고 호출하는 것에 비해 코드를 더 간결하게 작성할 수 있어요. 이는 특히 간단한 기능을 수행하는 코드 블록에 대해 유용하고 코드의 가독성을 향상시킬 수 있답니다.
forEach
함수를 사용하여 각 재료를 게살버거에 추가하는 코드도 하나 더 보실게요!
let 게살버거재료 = ["빵", "게살패티", "치즈", "양상추", "토마토"]
func 재료추가(재료: String) {
print("\(재료)를 게살버거에 추가합니다.")
}
게살버거재료.forEach(재료추가)
보시다시피 함수 없이 훨씬 간단하게 구현이 가능하죠?
let 게살버거재료 = ["빵", "게살패티", "치즈", "양상추", "토마토"]
게살버거재료.forEach { 재료 in
print("\(재료)를 게살버거에 추가합니다.")
}
foreach 메서드는 제가 addSubviews할때도 굉장히 애용중입니다 ㅎㅎ
클로저의 장단점
- 장점
- 여러 작업을 동시에 처리하거나, 코드의 실행을 연기하거나, 코드를 '캡슐화'하여 한 덩어리로 관리하는 데에 매우 유용합니다.
- 클로저는 간결하게 코드를 작성할 수 있도록 도와줍니다.
- 단점
- 클로저의 캡처 특성 때문에 순환 참조의 위험이 있습니다. 따라서 메모리 관리에 주의해야 합니다.
- 클로저의 사용이 복잡해질수록 코드의 가독성이 떨어질 수 있습니다.
언제 많이 사용하나요?
클로저는 네트워크 요청이나 애니메이션 완료 후 특정 작업을 수행하는 등 비동기 작업에서 많이 사용됩니다.
클로저의 활용
클로저는 변수나 상수 등에 할당할 수 있으며, 함수의 매개변수로 전달하거나 결과값으로 반환할 수 있습니다.
집게사장이 주문을 받아 처리하는 것은 함수로, 그 과정에서 발생하는 요리 조리 과정을 클로저로 구현해볼게요.
func processOrder(order: String, completion: (String) -> Void) {
completion("주문하신 \(order)를 만들었습니다.")
}
let cooking: (String) -> Void = { order in
print("주문하신 \(order)를 만들고 있습니다.")
}
processOrder(order: "크랩버거", completion: cooking)
이 예시에서 cooking
이 바로 클로저입니다. 이 클로저는 processOrder
함수의 매개변수로 전달되어 주문이 처리되는 과정을 출력합니다.
클로저의 캡처리스트
클로저는 주변의 상수나 변수를 '캡처'할 수 있는데요, 캡처를 하면 클로저 내부에서 주변의 상수나 변수를 참조할 수 있습니다. 이를 '클로저의 캡처리스트'라고 해요.
클로저의 캡처리스트는 클로저가 생성될 때 주변 환경(context)의 변수나 상수를 '기억'하는 역할을 합니다.
우리가 일을 미루다가 나중에 그 일을 다시 진행할 때, 그 때의 상황을 기억하고 그에 맞춰 일을 하죠?
이처럼 클로저도 캡처리스트를 통해 생성 시점의 주변 환경의 상태를 '기억'하고 이를 이용해 나중에 독립적으로 동작해요.
var crabBurgerCount = 0
let addCrabBurger: () -> Void = { [crabBurgerCount] in
print("크랩버거 \(crabBurgerCount + 1)개를 추가했습니다.")
}
addCrabBurger()
이 예시에서 addCrabBurger
클로저는 crabBurgerCount
변수를 캡처하여 개수를 증가시킵니다.
클로저의 생략 문법
Swift의 클로저는 문법을 간소화할 수 있는 여러 가지 방법을 제공합니다. 예를 들어, 파라미터와 반환 타입을 생략하거나, 단축 인자 이름을 사용할 수 있습니다.
let orderProcessing: (String) -> String = { order in
return "주문하신 \(order)를 만들었습니다."
}
// 간소화 버전
let orderProcessing = { (order: String) in "주문하신 \(order)를 만들었습니다." }
위 코드처럼 클로저의 타입 추론 기능을 활용하면 파라미터와 반환 타입을 생략할 수 있어요. 그리고 단축 인자 이름을 사용하면 인자에 대한 별도의 이름을 지정하지 않고 클로저를 구현할 수 있습니다.
한 줄 요약
클로저는 코드의 재사용, 간결성, 비동기 처리 등을 위해 사용되는 독립적인 코드 블럭이고, 메모리 관리와 가독성에 주의해야 합니다.
'스폰지밥으로 공부하는 swift > swift 문법' 카테고리의 다른 글
너 T야? 어 제네릭이야~ (1) | 2024.02.08 |
---|---|
CodeBaseUI에서 UI컴포넌트를 선언하는 다양한 방법들 (0) | 2024.01.31 |
[값타입 vs 참조타입]을 '집게리아 레시피'로 이해 해보좌 (1) | 2024.01.28 |
final 왜 씀..? (0) | 2024.01.06 |
unowned vs weak 뭐가 다른데? (1) | 2024.01.04 |