Swift - 클로저(Closures)

이재원·2024년 8월 3일
0

Swift

목록 보기
9/13
post-thumbnail

오늘은 Swift에서 클로저에 대해 이야기해보려고 합니다.

클로저는 간단히 말해서 코드 덩어리라고 할 수 있어요. 이 코드 덩어리는 변수나 상수에 저장되거나, 함수에 전달되거나, 함수의 반환값이 될 수도 있죠. 다른 언어에서의 익명 함수나 람다 표현식과 비슷한 개념이라고 생각하면 됩니다.

클로저에는 크게 세 가지 형태가 있어요:
1. 전역 함수: 이름이 붙어있고, 어떤 값도 캡처하지 않는 클로저입니다.
2. 중첩 함수: 이름이 있고, 둘러싼 함수의 값을 캡처할 수 있는 클로저입니다.
3. 클로저 표현식: 주변의 값을 캡처할 수 있는, 이름 없는 클로저입니다.

이 중 '캡처'라는 단어가 나오는데, 이 부분에 대해서는 나중에 더 자세히 설명할게요. 지금은 클로저를 어떻게 사용하는지부터 살펴보죠.

클로저 표현식(Closure Expressions)

클로저 표현식은 이렇게 작성됩니다

{ (매개변수) -> 반환 타입 in
    실행할 코드
}

이 클로저는 파라미터로 inout과 가변 파라미터를 사용할 수 있어요. 그리고 파라미터나 반환 타입으로 튜플도 사용할 수 있죠. 하지만 기본값을 가질 수는 없어요.

아래는 sorted 메서드에서 클로저를 사용한 예제입니다

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)

위 코드는 이름 배열을 정렬하는 예제인데, 클로저를 사용하면 더 간단하게 할 수 있습니다

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

타입 추론(Inferring Type From Context)

정렬 클로저의 타입은 (String, String) -> Bool로 추론될 수 있어요. 그래서 반환 타입을 생략하고 이렇게 간단하게 작성할 수 있습니다

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 })

더 나아가서, return 키워드도 생략할 수 있어요

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 })

짧은 인수 이름(Shorthand Argument Names)

Swift는 인라인 클로저에서 $0, $1 같은 짧은 인수 이름을 제공합니다. 이렇게 사용하면 코드가 더 깔끔해지죠

reversedNames = names.sorted(by: { $0 > $1 })

후행 클로저(Trailing Closure)

후행 클로저는 함수의 마지막 매개변수로 클로저를 전달할 때 사용하는 방법인데, 이렇게 하면 코드의 가독성이 좋아집니다.

someFunctionThatTakesAClosure() {
    // 클로저의 본문
}

sorted 함수에서도 후행 클로저를 사용할 수 있습니다

reversedNames = names.sorted { $0 > $1 }

캡처값(Capturing Values)

캡처란, 클로저 내부에서 사용되는 외부 변수나 상수를 클로저가 정의된 컨텍스트로부터 참조하는 것을 말해요. 이게 무슨 뜻이냐면, 클로저가 만들어질 때 그 주변에 있는 변수나 상수를 기억해 둔다는 거죠.

아래 예제를 보면 이해가 쉬울 거예요

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

이 함수에서 runningTotalamount는 클로저에 의해 캡처되기 때문에, 함수가 끝나더라도 값이 유지됩니다.

let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()  // 10을 반환
incrementByTen()  // 20을 반환

요약

  1. 클로저(Closure):
    • 코드의 기능 블럭으로 변수나 상수에 할당될 수 있고, 함수로 전달될 수 있으며반환 가능함.
    • 다른 프로그래밍 언어의 익명 함수, 람다와 유사.
  2. 클로저의 주요 형태:
    • 전역 함수: 이름이 있으며 어떠한 값도 캡처하지 않은 클로저.
    • 중첩 함수: 이름이 있으며 둘러싼 함수로부터 값을 캡처할 수 있는 클로저.
    • 클로저 표현식: 주변 컨텍스트에서 값을 캡처할 수 있는 경량 구문으로 작성된 이름 없는 클로저.
  3. 클로저 표현식(Closure Expressions):
    • 기본 형태: { (매개변수) -> 반환 타입 in 실행 코드 }
    • 파라미터는 inout과 가변 파라미터 모두 사용 가능, 튜플도 가능하지만 기본값은 불가.
  4. 타입 추론:
    • 컨텍스트로부터 클로저의 타입을 유추할 수 있어 반환 화살표 >와 파라미터의 소괄호 생략 가능.
  5. 짧은 인수 이름(Shorthand Argument Names):
    • Swift는 인라인 클로저에 $0, $1 등 짧은 인수 이름 제공, in 키워드 생략 가능.
  6. 후행 클로저(Trailing Closure):
    • 함수의 마지막 매개변수로 전달될 때, 함수 호출의 괄호 밖에 클로저 작성 가능, 가독성 향상.
  7. 캡처값(Capturing Values):
    • 클로저 내부에서 사용되는 외부 변수나 상수를 클로저가 정의된 컨텍스트로부터 참조, 참조 타입 특성으로 값 유지 가능.

마무리

클로저는 코드 덩어리로 변수나 상수에 할당될 수 있고, 함수로 전달되거나 반환될 수 있습니다. Swift의 클로저는 익명 함수나 람다와 유사하지만, 다양한 형태와 강력한 기능을 제공하죠. 특히 타입 추론, 짧은 인수 이름, 후행 클로저 등의 기능을 통해 클로저를 훨씬 간편하게 사용할 수 있습니다.

다음 시간에는 탈출 클로저에 대해 알아보겠습니다.

출처
https://bbiguduk.gitbook.io/swift/language-guide-1/closures#trailing-closures

profile
20학번 새내기^^(였음..)

0개의 댓글