클로저.....

BS_Lee·2025년 6월 24일

swift

목록 보기
7/21

Swift를 배우면서 가장 많이 마주치는 개념 중 하나가 바로 클로저(Closure)이다.
근데 이게 생긴 것도 낯설고, 문법도 헷갈리고, 대체 왜 쓰는지도 잘 모르겠다.
(이게 무슨소리인지 이해하는데 대략 2일정도 소요된거같다.... 허허)
(사실 완전히 이해하지는 못했지만, 계속 마주치면서 이해해보려고 한다.)


클로저란?

클로저는 이름 없는 함수이다.
그리고 이 함수는 변수처럼 저장하거나, 함수의 인자로 전달하거나, 함수에서 리턴할 수도 있다.

Swift에서는 아래처럼 쓴다:

let greet = {
    print("안녕하세요")
}
greet()  // 출력: 안녕하세요

그럼 여기서 궁금한 게 하나 생긴다.
"굳이 이렇게까지 해야 돼? 그냥 함수 쓰면 되는 거 아니야?"


클로저를 왜 써야 할까?

클로저는 실전에서 정말 많이 쓰인다. 그 이유는 이렇다.

  • 콜백 전달
    - 네트워크 요청 끝났을 때, 애니메이션 완료 시 등등
  • 상태 유지
    - 외부 변수 캡처해서 값 기억 가능 (→ 클로저 캡처)
  • 코드 간결
    - 짧고 일회성 로직에 딱 좋음
  • 지연 실행
    - 필요할 때만 실행되도록 할 수 있음

예를 들어 이런 함수가 있다고 하자.

func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

이건 count라는 값을 내부에서 유지하면서 점점 늘려주는 클로저를 리턴한다.

let counter = makeCounter()
counter()  // 1
counter()  // 2

이처럼 클로저는 함수 이상의 역할을 할 수 있다.
‘기억하는 함수’라고 생각하면 된다.


클로저를 어떻게 쓸까?

Swift에서 클로저는 여러 방식으로 정의할 수 있다.
(예시를 쭉 보면 감이 올지도.......?)

방식예시 코드
기본 정의let greet = { print("hi") }
파라미터 & 리턴let add = { (a: Int, b: Int) -> Int in return a + b }
타입 추론let add = { a, b in a + b }
축약 표현let add = { $0 + $1 }
함수 인자로 전달sorted(by: { $0 < $1 }) 또는 sorted { $0 < $1 }
함수에서 반환func makeAdder(x: Int) -> (Int) -> Int
변수 캡처클로저 안에서 외부 변수 사용 가능
@escaping비동기 작업 시 클로저를 나중에 실행할 때 사용
@autoclosure표현식 자체를 넘겨서 나중에 평가할 때 사용

예를 들어 이런 식으로도 쓸 수 있다:

func perform(action: () -> Void) {
    action()
}

perform {
    print("실행됨!")
}

→ 이런 방식은 trailing closure 문법이라고 부른다. 가독성이 훨씬 좋다.


클로저 예제 모음

함수에서 클로저 반환

func makeAdder(_ x: Int) -> (Int) -> Int {
    return { y in x + y }
}

let add5 = makeAdder(5)
add5(3)  // 결과: 8

고차 함수 사용

let nums = [1, 2, 3]
let squared = nums.map { $0 * $0 }  // [1, 4, 9]

@escaping 사용 예시

func asyncTask(completion: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        completion()
    }
}

→ 비동기에서 나중에 클로저를 실행해야 하니 @escaping을 붙여줘야 한다.


정리 한 줄 요약

클로저는 이름 없는 함수로, 콜백 전달이나 상태 유지, 코드 축약 등에 매우 유용하다.
Swift에서는 클로저 문법이 매우 강력하고 다양하기 때문에
map, filter, sorted 같은 고차 함수에서도 자주 활용된다.


  • JS의 () => {}, Python의 lambda, Java의 () -> {}와 개념적으로 비슷하다.
  • 하지만 Swift는 타입 안정성캡처 기능이 더 강력하다.
  • 단, 클로저가 변수/상수를 캡처하다가 메모리 누수(참조 순환)가 생길 수 있으니
    [weak self] 같은 문법도 꼭 알아두자.

0개의 댓글