티스토리 뷰

Study/Swift

클로저(Closure)란?

Corinee 2024. 10. 1. 12:52
728x90

클로저(Closure)는 스위프트에서 사용되는 코드 블록으로, 일종의 익명 함수 또는 코드 조각이라고 할 수 있습니다. 함수와 마찬가지로, 특정 작업을 수행하고 값을 반환할 수 있습니다. 하지만, 클로저는 자체적으로 이름이 없으며, 다른 변수나 상수에 저장하거나 함수의 인자로 전달할 수 있습니다.

스위프트의 클로저는 익명 함수(Anonymous Function)와 람다 표현식(Lambda Expression)과 유사합니다. 클로저는 함수형 프로그래밍 스타일을 지원하며, 컬렉션 데이터 처리나 비동기 작업 등에 자주 사용됩니다.

클로저의 기본 문법

클로저는 세 가지 형태를 가지고 있습니다:

  1. 전역 함수: 이름이 있고 특정 값에 바인딩되지 않는 클로저
  2. 중첩 함수: 이름이 있고, 특정한 함수의 내부에 정의되는 클로저
  3. 클로저 표현식: 간단한 문법으로 작성된 익명 클로저

클로저 표현식 기본 형태

다음은 클로저의 기본 문법입니다:

{ (parameters) -> ReturnType in
    // 클로저 코드
}
  • parameters: 함수의 매개변수처럼 클로저가 받아들이는 값의 목록입니다.
  • ReturnType: 클로저가 반환하는 값의 타입입니다.
  • in: 클로저 본문을 시작하는 키워드입니다.

클로저의 예제

1. 간단한 클로저

다음은 두 숫자를 더하는 간단한 클로저 표현식입니다:

let add: (Int, Int) -> Int = { (a: Int, b: Int) in
    return a + b
}

let result = add(3, 5)
print(result) // 8

위 코드에서 add는 (Int, Int) -> Int 타입의 클로저입니다. 이 클로저는 두 개의 Int를 받아서 Int를 반환합니다.

2. 함수의 인자로 전달되는 클로저

클로저는 함수의 인자로 전달될 수 있습니다. 아래는 클로저를 인자로 받아 실행하는 함수의 예시입니다:

func performOperation(operation: (Int, Int) -> Int, a: Int, b: Int) -> Int {
    return operation(a, b)
}

let result = performOperation(operation: add, a: 10, b: 20)
print(result) // 30

performOperation 함수는 (Int, Int) -> Int 형태의 클로저를 인자로 받아 이를 실행합니다.

3. 후행 클로저(Trailing Closure)

클로저가 함수의 마지막 인자로 전달될 때, 매개변수 이름을 생략하고 함수 호출 구문 밖에 클로저 코드를 작성할 수 있습니다.

let numbers = [1, 2, 3, 4, 5]
let doubledNumbers = numbers.map { (number) in
    return number * 2
}

print(doubledNumbers) // [2, 4, 6, 8, 10]

위의 코드에서 numbers.map 메서드는 후행 클로저를 사용하여 배열의 각 요소를 두 배로 만듭니다.

클로저의 간소화(Syntax Optimization)

스위프트에서는 클로저 표현을 간단하게 작성하기 위해 여러 가지 최적화 문법을 제공합니다:

1. 매개변수와 반환 타입 추론

스위프트는 클로저의 매개변수와 반환 타입을 추론할 수 있습니다. 따라서 타입을 생략할 수 있습니다.

let multiply = { a, b in
    return a * b
}

2. 단축 인자 이름(Shorthand Argument Names)

매개변수 이름을 생략하고, $0, $1와 같은 단축 인자를 사용할 수 있습니다.

let tripledNumbers = numbers.map { $0 * 3 }
print(tripledNumbers) // [3, 6, 9, 12, 15]

클로저와 캡처(Capture)

클로저는 주변 컨텍스트에 있는 변수나 상수를 캡처하여 내부에서 사용할 수 있습니다.

func makeIncrementer(by amount: Int) -> () -> Int {
    var total = 0
    let incrementer: () -> Int = {
        total += amount
        return total
    }
    return incrementer
}

let incrementByFive = makeIncrementer(by: 5)
print(incrementByFive()) // 5
print(incrementByFive()) // 10

위 예제에서 incrementer 클로저는 total과 amount를 캡처하여 클로저 내부에서 사용합니다. 이렇게 클로저는 자신이 정의된 주변 환경의 값을 기억하고 사용할 수 있습니다.

클로저와 @escaping

위에서 설명했듯이, 클로저를 함수의 인자로 전달할 때 클로저가 함수의 실행이 끝난 후에도 실행될 수 있다면 @escaping 키워드를 사용해야 합니다. 이는 주로 비동기 작업에서 사용됩니다.

정리

  • 클로저는 이름 없는 코드 블록이며, 변수나 상수에 저장하거나 함수에 인자로 전달할 수 있습니다.
  • 클로저는 매개변수와 반환 타입을 가지며, 다양한 형태로 표현할 수 있습니다.
  • 후행 클로저, 단축 인자 이름, 타입 추론 등의 문법을 활용해 코드를 간결하게 작성할 수 있습니다.
  • 클로저는 주변 컨텍스트의 변수와 상수를 캡처하여 내부에서 사용할 수 있습니다.
  • @escaping은 클로저가 함수의 범위를 벗어나서 실행될 수 있을 때 사용하는 키워드입니다.

클로저는 스위프트에서 콜백, 비동기 작업, 함수형 프로그래밍 등의 다양한 상황에서 매우 유용하게 사용됩니다.

 
 
 
 

 

 
 
728x90