Jupyo's Daily Story
클로저 (Closures) 본문
클로저(Closures)는 코드 블록을 나타내며, Swift에서 일급 객체로 다룰 수 있는 익명 함수입니다. 함수처럼 매개변수, 반환 타입을 가질 수 있으며, 변수나 상수에 할당될 수 있습니다. 또한, 클로저는 외부 변수를 캡처하여 해당 변수를 내부에서 사용할 수 있습니다.
클로저의 특징
- 익명 함수: 이름 없이 코드 블록 자체를 작성할 수 있습니다.
- 캡처 기능: 클로저 내부에서 함수 외부의 값을 참조하고 변경할 수 있습니다.
- 간결한 표현: 클로저는 문법을 단축하여 간결하게 사용할 수 있습니다.
기본 구조
{ (매개변수) -> 반환타입 in
실행할 코드
}
클로저의 사용 예
let multiply = { (a: Int, b: Int) -> Int in
return a * b
}
print(multiply(3, 4)) // 출력: 12
후행 클로저(Trailing Closures)
함수의 마지막 인자가 클로저일 때, 후행 클로저 구문을 사용하여 코드 가독성을 높일 수 있습니다.
func execute(action: () -> Void) {
action()
}
execute {
print("클로저 실행")
}
캡처링(Capturing Values)
클로저는 외부의 변수나 상수를 캡처할 수 있습니다. 클로저가 선언될 때, 외부의 값들이 클로저 내에 캡처되고, 클로저 내부에서 해당 값을 참조하거나 수정할 수 있습니다.
var count = 0
let increment = {
count += 1
}
increment()
print(count) // 출력: 1
자동 클로저(Autoclosures)
자동 클로저는 매개변수 없이 클로저가 실행되도록 만들어주는 기능입니다. 주로 논리 연산에서 지연 평가를 사용할 때 유용합니다.
func log(_ message: @autoclosure () -> String) {
print(message())
}
log("자동 클로저 실행")
탈출 클로저(Escaping Closures)
일반적으로 클로저는 함수 내에서만 사용됩니다. 하지만 탈출 클로저는 함수가 끝난 뒤에도 실행될 수 있는 클로저입니다. 주로 비동기 작업에서 사용됩니다.
func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.global().async {
let data = "Fetched Data"
completion(data)
}
}
fetchData { data in
print(data)
}
클로저의 축약 표현
Swift에서 클로저는 매개변수와 반환 타입을 유추할 수 있으면, 문법을 간소화할 수 있습니다. 매개변수 이름을 생략하고, $0, $1 등을 사용하여 축약된 방식으로 작성할 수 있습니다.
let numbers = [1, 2, 3]
let doubled = numbers.map { $0 * 2 }
print(doubled) // 출력: [2, 4, 6]
클로저를 사용하는 흔함 함수
클로저는 콜백이나 함수형 프로그래밍 패턴에서 자주 사용됩니다. Swift의 고차 함수들, 예를 들어 map, filter, reduce 같은 함수들은 클로저를 사용하여 배열이나 컬렉션의 요소들을 다룹니다.
let names = ["Apple", "Banana", "Cherry"]
let uppercasedNames = names.map { $0.uppercased() }
print(uppercasedNames) // 출력: ["APPLE", "BANANA", "CHERRY"]
클로저와 async/await 비교
- 비동기 작업에서의 차이: 클로저는 비동기 작업에서 주로 탈출 클로저 형태로 사용되어 비동기 작업이 끝난 후 수행할 코드를 정의합니다. 하지만 클로저 기반의 코드는 중첩이 발생하면 복잡해질 수 있습니다. 반면 async/await는 비동기 코드를 동기처럼 작성할 수 있어 가독성이 뛰어나고, 코드 흐름을 더 쉽게 이해할 수 있게 해줍니다.
클로저 예시
func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.global().async {
let data = "Fetched Data"
completion(data)
}
}
fetchData { data in
print(data)
}
async/await의 예시
func fetchData() async -> String {
return "Fetched Data"
}
Task {
let data = await fetchData()
print(data)
}
결론적으로, 클로저는 Swift의 강력한 기능 중 하나로, 특히 비동기 작업에서 유용합니다. 하지만 코드가 복잡해질 경우 async/await가 더 직관적이고 가독성 높은 방법일 수 있습니다.
'Swift' 카테고리의 다른 글
콜렉션 타입(Collection Type) - 배열(Array) (2) | 2024.10.07 |
---|---|
ARC (Automatic Reference Counting) (4) | 2024.10.02 |
Codable (0) | 2024.09.30 |
OperationQueue (0) | 2024.09.26 |
Concurrency (async/await) (3) | 2024.09.26 |