Neoself의 기술 블로그

@Sendable 정리 본문

개발지식 정리/Swift

@Sendable 정리

Neoself 2025. 3. 6. 18:56

Swift 5.5에서 도입된 프로토콜로, 동시성 모델에서 특정 함수나 클로저가 스레드 간 안전하게 전달될 수 있음을 나타냅니다.

@Sendable 프로토콜을 적용할 경우, 클로저나 다양한 타입에서 캡처하는 값이 Sendable 프로토콜을 마찬가지로 준수하는지 컴파일에 검사해줍니다. 이로서, 안정적으로 데이터 경쟁을 방지할 수 있게 되는 것입니다.

따라서, @Sendable을 사용한다는 것은 적용된 대상이 Swift의 동시성 모델과 호환되도록 설계되었음을 명시적으로 나타내는 것입니다.

 

Sendable 프로토콜 적용이 가능한 타입

구조체

모든 저장 프로퍼티가 Sendable을 준수하면, 자동으로 Sendable을 준수합니다.

struct MyStruct: Sendable {
    let id: Int
    let name: String
}

 

열거형

associated value이 모두 Sendable을 준수하면 자동으로 Sendable을 준수합니다.

enum MyEnum: Sendable {
    case case1(Int)
    case case2(String)
}

 

클래스

Sendable을 준수하려면 아래 작업이 필요합니다.

  1. 클래스가 final로 선언되어야 합니다.
  2. 모든 저장 프로퍼티가 Sendable을 준수해야 합니다. 
  3. 프로퍼티가 불변(let)이어야 합니다.
final class MyClass: Sendable {
    let id: Int
    let name: String
    
    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

 

액터

기본적으로 Sendable을 준수하는 타입니다.

 

함수 및 클로저

클로저의 경우 캡처한 모든 값이 Sendable을 준수해야 합니다. 별도로 @Sendable을 명시해야 합니다.

let sendableClosure: @Sendable () -> Void = {
    print("This is a sendable closure")
}

 

컬렉션 타입

배열, 딕셔너리, 집합 등은 포함된 요소가 Sendable을 준수하면 자동으로 Sendable 프로토콜을 준수합니다.

let sendableArray: [Sendable] = [1, "Hello", true]

 

옵셔널

래핑된 값의 타입이 Sendable을 준수하면 자동으로 Sendable을 준수합니다.

let sendableOptional: Int? = 42

 

튜플

let sendableTuple: (Int, String) = (1, "Hello")

 

Sendable을 준수할 수 없는 경우

가변 프로퍼티(var)를 포함하는 타입은 가변 상태로 Sendable을 준수할 수 없습니다.

클래스가 가변상태를 포함하거나 스레드 안정성을 보장하지 않으면 Sendable을 준수할 수 없습니다.