iOS/Swift Concurrency

#isolation vs @isolated(any)

Hamp 2025. 5. 24. 18:37
반응형

👋 들어가기 전

https://hamp.tistory.com/212

 

Actor

👋 들어가기 전먼저 간단한 선행 내용을 먼저 정리한 이후 엘런님 강의를 듣고 나서 다시 한번 더 내용을 채우러 오겠다.🏁 학습할 내용Actor란 무엇인가특징 및 동작방식어떻게 동기화 메커니

hamp.tistory.com

 

이전 actor 포스팅 마지막 부분에서 우리는 nonisolated 키워드와 isolated키워드를 배웠고

https://hamp.tistory.com/218

 

@globalActor

👋 들어가기 전이번 포스팅은 글로벌 Actor라는 내용을 학습해보자.엑터를 공부한 이후, @MainActor를 공부했는데 , @MainActor처럼 쓸 수 있게 내가 커스텀으로 만들어낼 수 있는 방법이 있다.🏁 학습

hamp.tistory.com

글로벌 엑터 포스팅에서, 엑터를 앱 최상위 전역에서 사용할 수 있게 만들 수 있는 방법도 알아봤다.

 

정리하면 격리 엑터 지정은 3 종류가 있다.

  • 비격리 도메인
  • isolated로 전달된 actor 도메인
  • 글로벌 엑터 도메인

오늘 알아볼 내용은 actor 격리 도메인을 전달하는 방법론을 알아보자.

🏁 학습할 내용

  • #isolation
  • @isolated(any)

#️⃣ #isolation

우리는 actor 포스팅에서 isolated 키워드를 통해

actor 외부에서도, actor 내부에서처럼 격리된 환경 형태로 접근하는 방법을 배웠다.

func execute(actor: isolated MyActor) async {
  actor.a += 10
}

let myActor = MyActor()

Task {
  await execute(actor: myActor)
  print(await myActor.a)
}

 

이 때 특정 Actor를 MyActor로 한정시키는게 아닌, 다양한 Actor를 고려하거나

격리 시키고 싶지 않으면 어떻게 해야할까 ??

🅰️ Actor 프로토콜

첫번 째 우리는 특정 조건을 통해 다양한 타입을 받고 싶다면, 추상화가 가장 먼저 떠오른다.

즉, 상속 또는 프로토콜을 이용해야한다.

 

 

여기서 우리는 Actor라는 특정 조건이 있고 모든Actor는 Actor 프로코톨을 채택하므로

Actor 프로토콜을 이용할 수 있다.

 

⛓️‍💥 비격리 

특정 Actor를 격리 시키고 싶지 않을 때는, Actor를 입력하지 않으면된다.

이때 쓰는 내용이 옵셔널이다. 값이 있으면 특정 actor로 격리, 없으면 비격리

 

1️⃣ 두 조건을 합쳐보자.

프로토콜 타입 + 옵셔널을 합치면 다음과 같은 함수가 나온다.

(any Actor)?

func execute(actor: isolated (any Actor)?) async {

}

🤔 등장 배경

현재까지 조합으로 이 문제는 어떻게 해결해할까?

 

함수 호출 위치의 격리 컨텍스트를, 다음 함수에서도 계속 이용하고 싶을 때

 

그러면 우리는 다음 코드를 쓸 수 있다.

func execute1(actor: isolated (any Actor)?) async {
  await execute2(actor: actor)
}

func execute2(actor: isolated (any Actor)?) async {
  await execute3(actor: actor)
}

func execute3(actor: isolated (any Actor)?) async {

}

 

actor를 계속 넘겨준다. 그러나 굉장히 귀찮다.

이것을 시스템에 넘겨주면 어떨까?

 

이 때 필요한 키워드가 #isolation이다.

 

⭐️ 정의

공식 문서를 보면 현재 격리 actor를 반환한다.

만약 비격리거나 nonisolated 코드면 nil을 반환한다.

 

🎬 isolated (any Actor)? = #isolation

위 내용을 정리하면 다음과 같이 읽을 수 있다.

  1. 원하는 actor를 제공하면 해당 격리 컨텍스트를 사용한다.
  2. default 값으로는 현재 격리 actor를 반환한다.
  3. 만약 현재 actor가 없으면 nil을 반환하고
  4. nil은 격리 actor 없음, 즉 nonisolated를 의미한다.

⛓️ @isolated(any)

 

🤔 등장 배경

 

위에서 배운 isolated (any Actor)? = #isolation은 동적으로 엑터를 할당할 수도 있지만

#isolation 매크로를 통해 컴파일러가 현재 컨텍스트를 이어서 사용할 수도 있다.

 

이때 현재 컨텍스트를 이어서 사용할 때. 조금 더 간단히 하기위한 attribute이다.

 

이때 큰 차이점은, 현재 격리 컨텍스트를 이어서 사용하는 특징은 똑같지만

격리 정보까지도 함께 전달받아 이용할 수 있다는 특징있다.

 

⭐️ 정의

 

현재 격리 컨텍스트를 사용함과 동시에, 격리 정보도 함께 전달한다.

 

🌐 격리 정보

 

@isolated(any)가 붙으면 격리정보에 접근할 수 있는 isolation 프로퍼티를 사용할 수 있다.

 

📋 예제

import Foundation

func doSomething2(_ operation: @Sendable @escaping @isolated(any) () -> Void) {
    Task {
        print("2: \(operation.isolation)")
        await operation()
    }
}

func doSomething1(_ actor: isolated (Actor)? = #isolation, _ operation: @Sendable @escaping () -> Void) {

    Task {
      print("1: \(actor)")
      await operation()
    }
}

@globalActor
actor MyGlobalActor {
    static let shared = MyGlobalActor()
}

doSomething2 {
    // 출력 nil
}

doSomething2 { @MainActor in
    // 출력 Optional(Swift.MainActor)
}

doSomething2 { @MyGlobalActor in
    // 출력 Optional(__lldb_expr_92.MyGlobalActor)
}

doSomething1 {
    // #isolatino으로 인해 현재 actor context인 MainActor가 나옴
}

doSomething1(MainActor.shared) {
    // 출력 Optional(Swift.MainActor)
}

Task {
  await doSomething1(MyGlobalActor.shared){
      // 출력 Optional(__lldb_expr_631.MyGlobalActor)
  }
}

 

결과를 살펴보면 현재 격리 컨텍스트가 둘다 잘 넘어가고 있지만

doSomething2 함수는 actor를 따로 파라미터로 넣지 않고 호출부분에 정의하며

안에서 isolation 프로퍼티를 통해 격리 정보를 알 수 있지만 

 

doSomething1 함수는 actor를 넣어주거나, #isolation 매크로를 통해 시스템에서 반환해서 알려준다.


😀 소감 및 마무리

키워드 isolated (Actor)? = #isolation @isolated(any)
격리 정보 전달 가능 여부 X O
동적으로 actor 할당 여부 O X
사용 대상 엑터 파라미터 함수 타입 파라미터

출처

https://github.com/swiftlang/swift-evolution/blob/main/proposals/0431-isolated-any-functions.md

 

swift-evolution/proposals/0431-isolated-any-functions.md at main · swiftlang/swift-evolution

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution

github.com

https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md

 

swift-evolution/proposals/0420-inheritance-of-actor-isolation.md at main · swiftlang/swift-evolution

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swiftlang/swift-evolution

github.com

https://eunjin3786.tistory.com/672

 

[Swift] @isolated(any)

✓ SE-0431 @isolated(any) Function Types 📝 Assisted by GPT  [1] @isolated(any)  @isolated(any) 은 swift 6 에 추가된 attribute 입니다. (function only)임의의 (하지만 정적으로 알 수 없는) 격리를 가진 함수를 표현할

eunjin3786.tistory.com

https://developer.apple.com/documentation/swift/isolation()

 

isolation() | Apple Developer Documentation

Produce a reference to the actor to which the enclosing code is isolated, or if the code is nonisolated.

developer.apple.com

 

반응형