Swift 6 의 시작입니다...
해당 글을 작성하기 위해서 현재 출시 제작중인 앱을 Swift6 로 전환하는 과정을
거쳤는데요... Panic 이 올수 밖에 없습니다. 천천히 진행해 보겠습니다.
불투명한 타입(opaque Type), 암시적 반환 및 모듈 형식 안정성을 추가했습니다.
함수로서의 키 경로 표현과 개선된 진단 기능을 가져왔습니다.
다중 패턴 에러 핸들링 ( catch ), 여러 후행 클로저, 그리고 Swift 패키지 매니저 개선 등 다양한 언어 개선을 가져왔습니다.
함수 내에서 다중 가변 매개변수 지원과 결과 빌더를 추가했습니다.
async/await, async 시퀀스, 구조화된 동시성, 액터, 글로벌 액터, Sendable 프로토콜/클로저와 같은 동시성에 중점을 둔 기능을 대규모로 업데이트했습니다.
타입 플레이스홀더와 존재하는 Any와 같은 동시성 및 언어 개선했습니다. 또한 Swift 패키지 매니저에 대한 플러그인을 추가했습니다.
옵셔널의 간결한 구문 해제, Swift Regex, C API와의 개선된 상호 운용성, 동시성 개선 및 더 작고 빠른 표준 라이브러리 기능을 도입했습니다.
결과 빌더에서 변수의 제한을 완화하고, 암시적 self를 개선했으며, 함수의 뒤로 배포를 허용했습니다.
제네릭을 값 및 타입 매개변수 팩으로 향상시켜 SwiftUI에서 10개 뷰 제한을 제거했으며, 매크로를 추가하고, if 및 switch 표현식으로 제어 흐름을 개선, 작업 그룹을 버릴 수 있는 기능을 추가했습니다.
모든 정적 데이터 레이스 안전성 구멍을 완전한 엄격한 동시성 검사로 해결합니다. 이는 글로벌 및 정적 변수를 사용할 때 데이터 레이스를 방지하는 엄격한 동시성을 도입합니다. 또한, 액터 외부에서 동기적으로 평가될 수 있었던 데이터 레이스 안전성 구멍을 해결하는 격리된 기본값 표현식을 도입합니다.
자 이제 Swift6 입니다.
이번 시간에는 Swift Concurrency 강화를 다루어 보겠습니다.
이부분이 가장Panic
하거든요.
사실 말보다는 직접 경험해봐야 뼈저리게 느껴지니 바로 코드를 보면서
문제를 이해해 보겠습니다.
예시로 싱글톤 패턴을 가져와 보았습니다.
final class CodableManager {
static let shared = CodableManager()
private init () {}
private let encoder = JSONEncoder()
private let decoder = JSONDecoder()
}
extension CodableManager {
func jsonEncoding<T: Encodable>(from value: T) throws -> Data {
return try encoder.encode(value)
}
func jsonDecoding<T:Decodable>(model: T.Type, from data: Data) throws -> T {
return try decoder.decode(T.self, from: data)
}
func toJSONSerialization(data: Data?) -> Any? {
do {
guard let data else {
return nil
}
return try JSONSerialization.jsonObject(with: data, options: [])
} catch {
return nil
}
}
}
위와같이 Decode, Encode 를 관리하는 매니저 클래스를 다루어 보려고 합니다.
Swift 5.x 에선 정말 잘 짜여진 코드 같습니다.
하지만 Swift 6 에선 매우 화가나는 코드인가 봅니다. 문제를 해석해보죠
정적 속성 'shared'는 'Sendable' 유형이 아닌 'CodableManager'가 변경 가능한 상태를 공유할 수 있으므로 동시성에 안전하지 않습니다.
많은 커뮤니티에선 이 에러 덕분에 많은 골머리를 앓고 있습니다.
답은 간단합니다. 데이터 레이스가 발생할 여지가 있다 라는 에러이죠.
하지만 해당 클래스 에서는 사실 데이터 레이스가 일어날 문제가 없습니다.
Sendable 검사를 하지 마요. 를 명시하여 이를 해결할수 있긴합니다...만.
동시성 상황에서 데이터 레이스가 날 가능성이 있을수도 있는데 무조건 이방법을 통해 해결하는 방법은
좋지 않습니다.
사진과 같이 이를 Sendable하게 구조를 조정하여
문제를 해결하는 방법입니다.
Actor는 Sendable을 채택하고 있습니다. 해당 방법으로도 해당 문제를 해결할수 있겠죠.
protocol Actor : AnyObject, Sendable
하지만 Actor편을 보셨다면 아시겠지만 해당 클래스는 사실 비동기적으로도, 동시성으로도 전혀 문제있는
코드가 아니라고 저는 생각합니다.
그래서 해당하는 클래스를 바라보았을때는 Actor화 하기에는 애매하다고 생각합니다.
확실히 Swift Concurrency 를 열심히 공부해야 하는 시대가 온 것 같습니다.
이번 편이 이해가 안된다면 꼭 Swift Concurrency 편을 전부 보고 다시 봐주시길 바랍니다.
iOS 19.... Swift6.... 파이팅...!