Sendable 프로토콜을 준수하는 Swift의 한 타입입니다.
<aside> 👉 Actor는 단순히 Swift의 타입 중 하나입니다. Struct, Enum, Class 등과 비슷한 능력을 가지고 있습니다. 특히 Class와 비슷한데, Actor도 Class와 같은 참조 타입이기 때문입니다. 프로퍼티, 이니셜라이저, 메서드, subscript 등을 가질 수 있고, 프로토콜 conform이나 extension을 통한 확장도 가능합니다.(단, 상속은 지원하지 않습니다)
</aside>
Actor Isolation
이라는 개념을 이용해 보호하고, 이 데이터에 대한 동기화된 접근을 보장해 준다는 것입니다.(data race의 문제가 없다는 것입니다)<aside> ❓ Actor Isolation: Actor의 mutable한 상태를 외부로부터 고립시켜 보호하는 개념
</aside>
위와 같이 동시성의 바다 위에 떠 있는 섬 Actor가 있고, 섬 외부인 바다로부터 보호받고 있는 양과 파인애플이 있다고 해 봅시다. 이때 Sheep은 Class(참조타입), Pineapple은 Struct(값 타입)입니다.
간단히 코드로 구현하면 다음과 같습니다.
actor Island {
// Class 타입 프로퍼티
var animal: [Sheep]
// Struct 타입 프로퍼티
var food: [Pineapple]
// 섬에 있는 자원 정보
func calculate() {
let totalBrix = food.indices.reduce(0) { total, nextIndex in
total + food[nextIndex].brix
}
print("파인애플 총 당도: \\(totalBrix)")
Task {
let sheepNames = animal.map { $0.name }
print("첫번째 양 이름은 \\(sheepNames[0])입니다.")
}
Task.detached {
let highBrixPineapples = await self.food.filter { $0.brix == 12 }
print("당도 12: \\(highBrixPineapples.count)개")
}
}
// Class 반환 함수
func adoptPet() -> Sheep {
return animal[0]
}
// Struct 반환 함수
func getFood() -> Pineapple {
return food[0]
}
/// Initializer
init(animal: [Sheep], food: [Pineapple]) {
self.animal = animal
self.food = food
}
이 actor를 다음과 같이 사용하면, class 타입인 Sheep을 사용할 때 많은 에러가 발생합니다.
“Sendable” 프로토콜을 준수하지 않는 Sheep 클래스는 actor의 경계를 넘어갈 수 없다는 것입니다. 즉 Sendable이 아니면 actor 밖으로 전달될 수 없습니다.
class Counter {
let counterName = "Counter Class"
var count = 0
func increment() -> Int {
count = count + 1
return count
}
}
let counter = Counter()
Task.detached {
print(counter.increment())
}
Task.detached {
print(counter.increment())
}