https://developer.apple.com/videos/play/wwdc2024/10169/
해당 포스트는 위 영상을 기반으로 개인적으로 메모/정리한 글입니다.
개요
기존 코드를 Swift 6 로 Migrate 하면서 컴파일러가 어떻게 data race 위험성을 잡아내는지 알아보자. Data 를 isolation 시키는 테크닉과 공유 mutable state 에 대한 동시 접근을 없애는 테크닉을 배워보자.
Swift 6 로의 Migrate 장점
- Swift 6는 완전히 data isolation 를 보장하도록 만든다.
- Data race 때문에 재현이 힘든 크래시를 만난 경험이 있다면 당장 Swift 6 로 코드를 업데이트하라.
Migrate 순서
1. Xcode 16 Open
이 상태로도 이미 워닝은 발생한다.
2. Complete checking
2-a. [Target] 의 Build Setting → Strict Concurrency Checking: complete 로 설정
2-b. 빌드 후 컴파일러가 잡아주는 data race 관련 워닝을 수정해주기
참고로, nonisolated(unsafe) 키워드 사용해서 워닝 지우기 가능(lint disable 같은 느낌).
3. enable Swift 6 Mode
[Target] 의 Build Setting → Swift Language Mode → Swift 6
Migration Example
대부분은 워닝에서 해결책을 제시해준다.
Ex1) Shared mutable state in global variables
웬만하면 let 으로 만드세요 아니면 @MainActor 로 만드세요.
Q. let 이라도 lazy init 시점에서 두 개의 스레드가 동시 접근할 수 있지 않느냐?
A. 자동으로 atomic 하게 동작 됨.
Ex2) Shared mutable state in global instances and functions
이 글로벌 함수를 MainActor로 만들 수 있다.
Delegate callbacks 과 동시성
딜리게이트의 콜백이 어느 스레드에서 호출되는지는 동시성 환경에서 중요한 문제임.
대부분의 최신 View 관련 프레임워크는 딜리게이트 콜백을 전부 메인스레드에서 호출해준다. (애초에 MainActor 로 정의됨)
그러나 어떤 것들은 메인스레드에서 불린다는 보장이 안 된다. (ex: Apple의 HealthKit) 이 경우는 딜리게이트를 구현하는 쪽에서 올바른 큐에서 콜백 작업이 보장되도록 신경을 써야 함. 개발자에게 짐이 되는 작업이다. → Swift Concurrency 에서 `이것을 보장하거나, 보장하지 않는다`는 것을 명시적으로 나타내준다.
- 콜백에 대한 명세가 없는 경우: non-isolated 로 간주되며 isolation 이 필요한 데이터에 접근 못 하게 함.
- 콜백이 isolation 보장을 명시하는 경우: 콜백을 받는 쪽에서는 이 보장을 신뢰할 수 있음
public protocol CoffeineThresholdDelegate: AnyObject {
@MainActor func caffeineLevel(at level: Double)
}
(ex: 항상 main actor에서 콜백을 호출하겠다)
Data between actors
currentDrinks(Drink Struct)가 사실상 sendable 타입이라도, 이것이 다른 모듈의 Public type 이라면 Swift 는 자동으로 sendability 를 추론해주지 않는다.
만약 위처럼 Sendable 을 명시할 수 없는 타입이라면? (ex: NSObject 등)
nonisolated(unsafe) 키워드를 사용할 수 있다. 이때는 개발자가 알아서 보장해주기.
내가 소유하지 않은 코드를 다룰 때
MainActor.assumeIsolated: Swift 컴파일러에게 ‘이건 main actor에서 실행되고 있다’고 알려주는 것. (main actor 에서 새로운 task 를 시작시키는 게 아님을 주의)
main actor 가 아닌 곳에서 이 코드가 불릴 때는 trap 이 발생해서 실행 중에 프로그램이 멈춘다. (마치 assert 의 역할을 함) → data race condition 보다는 trap 으로 알려주는 게 낫다는 판단
shorthand: @preconcurrency
Common patterns and an incremental strategy
Migration 을 시작하면 엄청나게 많은 워닝이 처음엔 발생할 수 있다. 패닉하지 말 것. 아래 매뉴얼을 따라 차근차근 수정해나가면 된다.
- 간단하게 해결 가능한 이슈들을 먼저 해결하기 → main actor, immutable 등
- 많은 이슈들의 근원이 되는 원인을 찾아보기 → 한 줄 수정으로 해결되는 여러 개의 워닝들
- 최신 SDK, 최신 Xcode 를 적용하기 → 수정을 도와줄 어노테이션들이 적용된다.
- Take your time → 무리해서 급하게 Migrate 하지 않아도 된다.
'WWDC > 2024' 카테고리의 다른 글
Explore Swift performance (0) | 2024.08.08 |
---|---|
Demystify explicitly built modules (추천세션!) (0) | 2024.08.08 |
Consume noncopyable types in Swift (0) | 2024.08.08 |
A Swift Tour: Explore Swift’s features and design (0) | 2024.08.07 |
What’s new in App Store Connect (0) | 2024.08.07 |