Swift 함수와 클로저 | 함수 정의, 클로저, 고차 함수
이 글의 핵심
Swift 함수와 클로저에 대한 실전 가이드입니다. 함수 정의, 클로저, 고차 함수 등을 예제와 함께 상세히 설명합니다.
들어가며
함수는 일급 값으로 다루어지며, 클로저 문법으로 짧은 콜백을 쓰기 좋습니다. @escaping 여부로 수명을 컴파일러와 맞출 수 있습니다.
1. 함수 정의
기본 함수
func greet(name: String) {
print("안녕하세요, \(name)님!")
}
greet(name: "홍길동") // 안녕하세요, 홍길동님!
// 반환값이 있는 함수
func add(a: Int, b: Int) -> Int {
return a + b
}
let result = add(a: 3, b: 5)
print(result) // 8
// 반환값이 한 줄이면 return 생략 가능
func multiply(a: Int, b: Int) -> Int {
a * b
}
매개변수 레이블
// 외부 레이블과 내부 레이블
func greet(to name: String, from sender: String) {
print("\(sender)가 \(name)에게 인사합니다")
}
greet(to: "홍길동", from: "김철수")
// 외부 레이블 생략
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
let sum = add(3, 5) // 레이블 없이 호출
기본 매개변수
func greet(name: String = "Guest", greeting: String = "안녕하세요") {
print("\(greeting), \(name)님!")
}
greet() // 안녕하세요, Guest님!
greet(name: "홍길동") // 안녕하세요, 홍길동님!
greet(name: "홍길동", greeting: "반갑습니다") // 반갑습니다, 홍길동님!
가변 매개변수
func sum(_ numbers: Int...) -> Int {
var total = 0
for number in numbers {
total += number
}
return total
}
print(sum(1, 2, 3)) // 6
print(sum(1, 2, 3, 4, 5)) // 15
inout 매개변수
func swap(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swap(&x, &y)
print("x: \(x), y: \(y)") // x: 20, y: 10
2. 클로저 (Closures)
기본 클로저
let add = { (a: Int, b: Int) -> Int in
return a + b
}
let result = add(3, 5)
print(result) // 8
// 타입 추론
let multiply: (Int, Int) -> Int = { a, b in
a * b
}
// 단축 인자 이름
let subtract: (Int, Int) -> Int = { $0 - $1 }
후행 클로저 (Trailing Closure)
let numbers = [1, 2, 3, 4, 5]
// 일반 문법
let doubled = numbers.map({ $0 * 2 })
// 후행 클로저
let tripled = numbers.map { $0 * 3 }
// 여러 줄
let filtered = numbers.filter { number in
number % 2 == 0
}
3. 고차 함수
map, filter, reduce
Swift의 고차 함수를 사용한 배열 처리입니다:
let numbers = [1, 2, 3, 4, 5]
// 1. map: 각 요소를 변환
let doubled = numbers.map { $0 * 2 }
// { $0 * 2 }: 클로저 (후행 클로저 문법)
// $0: 첫 번째 인자 (현재 요소)
// 각 요소에 2를 곱함
// [1, 2, 3, 4, 5] → [2, 4, 6, 8, 10]
print(doubled) // [2, 4, 6, 8, 10]
// map 실전 예시: 객체 배열 변환
struct User {
let name: String
let age: Int
}
let users = [User(name: "홍길동", age: 25), User(name: "김철수", age: 30)]
let names = users.map { $0.name }
print(names) // ["홍길동", "김철수"]
// 2. filter: 조건을 만족하는 요소만 선택
let evens = numbers.filter { $0 % 2 == 0 }
// { $0 % 2 == 0 }: 짝수 판별 클로저
// true를 반환하는 요소만 포함
// [1, 2, 3, 4, 5] → [2, 4]
print(evens) // [2, 4]
// filter 실전 예시: 성인만 필터링
let adults = users.filter { $0.age >= 18 }
// 3. reduce: 배열을 하나의 값으로 축약
let sum = numbers.reduce(0) { $0 + $1 }
// reduce(초기값, 클로저)
// $0: 누적값 (accumulator), 처음엔 0
// $1: 현재 요소
//
// 동작 과정:
// $0=0, $1=1 → 0+1=1
// $0=1, $1=2 → 1+2=3
// $0=3, $1=3 → 3+3=6
// $0=6, $1=4 → 6+4=10
// $0=10, $1=5 → 10+5=15
print(sum) // 15
// reduce 간단 문법 (연산자 전달)
let sum2 = numbers.reduce(0, +)
// +: 함수처럼 전달 가능
print(sum2) // 15
// 4. 체이닝: 여러 고차 함수 연결
let result = numbers
.filter { $0 % 2 == 0 } // 짝수만: [2, 4]
.map { $0 * 2 } // 2배: [4, 8]
.reduce(0, +) // 합계: 12
print(result) // 12 (4+8)
// 실전 예시: 평균 계산
let average = numbers.reduce(0, +) / numbers.count
print(average) // 3
고차 함수의 장점:
- 가독성: 의도가 명확함
- 간결성: 반복문보다 짧음
- 불변성: 원본 배열 변경 없음
- 체이닝: 여러 연산 연결 가능
compactMap, flatMap
let strings = ["1", "2", "three", "4"]
// compactMap: nil 제거
let numbers = strings.compactMap { Int($0) }
print(numbers) // [1, 2, 4]
// flatMap: 중첩 배열 평탄화
let nested = [[1, 2], [3, 4], [5]]
let flattened = nested.flatMap { $0 }
print(flattened) // [1, 2, 3, 4, 5]
4. 캡처 (Capture)
func makeIncrementer(increment: Int) -> () -> Int {
var total = 0
let incrementer = {
total += increment
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(increment: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
print(incrementByTwo()) // 6
5. 실전 예제
예제: 사용자 필터링
struct User {
let name: String
let age: Int
let isActive: Bool
}
let users = [
User(name: "홍길동", age: 25, isActive: true),
User(name: "김철수", age: 17, isActive: false),
User(name: "이영희", age: 30, isActive: true),
]
// 활성 성인 사용자
let activeAdults = users
.filter { $0.isActive && $0.age >= 18 }
.map { $0.name }
print(activeAdults) // ["홍길동", "이영희"]
정리
핵심 요약
- 함수: func, 매개변수 레이블, 기본값
- 클로저: 익명 함수, 단축 문법
- 고차 함수: map, filter, reduce
- 캡처: 외부 변수 참조
- @escaping: 비동기 클로저
다음 단계
- Swift 클래스와 구조체
- Swift 프로토콜
- Swift 제네릭
관련 글
- JavaScript 함수 | 함수 선언, 화살표 함수, 콜백, 클로저 완벽 정리
- Kotlin 함수 | 함수 정의, 람다, 고차 함수
- C++ 기본 인자 |
- C++ 람다 캡처 에러 |
- C++ 이름 은닉 |