[2026] Swift 함수와 클로저 | 함수 정의, 클로저, 고차 함수

[2026] Swift 함수와 클로저 | 함수 정의, 클로저, 고차 함수

이 글의 핵심

Swift 함수와 클로저: 함수 정의, 클로저, 고차 함수. 함수 정의·클로저 (Closures).

들어가며

함수는 일급 값으로 다루어지며, 클로저 문법으로 짧은 콜백을 쓰기 좋습니다. @escaping 여부로 수명을 컴파일러와 맞출 수 있습니다.

실무에서 마주한 현실

개발을 배울 때는 모든 게 깔끔하고 이론적입니다. 하지만 실무는 다릅니다. 레거시 코드와 씨름하고, 급한 일정에 쫓기고, 예상치 못한 버그와 마주합니다. 이 글에서 다루는 내용도 처음엔 이론으로 배웠지만, 실제 프로젝트에 적용하면서 “아, 이래서 이렇게 설계하는구나” 하고 깨달은 것들입니다. 특히 기억에 남는 건 첫 프로젝트에서 겪은 시행착오입니다. 책에서 배운 대로 했는데 왜 안 되는지 몰라 며칠을 헤맸죠. 결국 선배 개발자의 코드 리뷰를 통해 문제를 발견했고, 그 과정에서 많은 걸 배웠습니다. 이 글에서는 이론뿐 아니라 실전에서 마주칠 수 있는 함정들과 해결 방법을 함께 다루겠습니다.

1. 함수 정의

기본 함수

다음은 swift를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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
}

매개변수 레이블

아래 코드는 swift를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// 외부 레이블과 내부 레이블
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)  // 레이블 없이 호출

기본 매개변수

아래 코드는 swift를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

func greet(name: String = "Guest", greeting: String = "안녕하세요") {
    print("\(greeting), \(name)님!")
}
greet()  // 안녕하세요, Guest님!
greet(name: "홍길동")  // 안녕하세요, 홍길동님!
greet(name: "홍길동", greeting: "반갑습니다")  // 반갑습니다, 홍길동님!

가변 매개변수

아래 코드는 swift를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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 매개변수

아래 코드는 swift를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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)

기본 클로저

아래 코드는 swift를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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)

아래 코드는 swift를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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의 고차 함수를 사용한 배열 처리입니다: 다음은 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

고차 함수의 장점:

  1. 가독성: 의도가 명확함
  2. 간결성: 반복문보다 짧음
  3. 불변성: 원본 배열 변경 없음
  4. 체이닝: 여러 연산 연결 가능

compactMap, flatMap

아래 코드는 swift를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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)

다음은 swift를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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. 실전 예제

예제: 사용자 필터링

다음은 swift를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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)  // ["홍길동", "이영희"]

정리

핵심 요약

  1. 함수: func, 매개변수 레이블, 기본값
  2. 클로저: 익명 함수, 단축 문법
  3. 고차 함수: map, filter, reduce
  4. 캡처: 외부 변수 참조
  5. @escaping: 비동기 클로저

다음 단계


관련 글

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3