-
RxSwift Single Swift6 대응하기Swift 2025. 4. 11. 18:00반응형
기존에 RxSwift 특히 Single을 사용하던 부분에서 Swift6 대응하며 삽질했던 겪었던 어려움을 남겨봅니다.
# 배경
먼저 기존 저희 코드에서 Network 통신을 처리하는 부분은 업데이트를 거듭하며
completionHandelr, async, rx 3가지 버전이 있었습니다.completion 방식이 제일 기본이고 이를 래핑해서 아래 버전들로 만들어 둔 상태였습니다.
- async (swift concurrency)
- single (rx)대강 아래와 같은 형태입니다.
// completion handler 방식 func get<T: Decodable>(url: String, completion: @escaping: (response: T?) -> Void { }
// Rx func get<T: Decodable>(url: String) -> Single<T> { return Single.create { observer -> Disposable in get(url) { response in observer(.success(response)) } return Disposables.create() } }
// Async func get<T: Decodable>(url: String) async throws -> T { return try await withCheckedThrowingContinuation { continuation in get(url: url) { response in continuation.resume(returning: response) } } }
# 문제
Swift6 가 되면서 Rx 버전의 코드에서 워닝이 발생합니다.
Capture of 'event' with non-sendable type '(Result<Response, any Error>) -> Void' in a `@Sendable` closure; this is an error in the Swift 6 language mode
// Rx func get<T: Decodable>(url: String) -> Single<T> { return Single.create { observer -> Disposable in get(url) { response in observer(.success(response)) // ❌ 문제 부분 } return Disposables.create() } }
Single의 구현을 보면 observer 인 SingleObserver는 Sendable이 아닙니다.
따라서 Sendable이 아닌 observer를 get completion handler의 클로져 내에서 캡처하기 때문에 문제가 됩니다.저 같은 경우 이에 대해서 검색해도 제대로 나오지 않고 GPT 한테 물어봐도 async로 감싸라, sendable closure 로 감싸라 등등 잘못된 답을 계속 받아서 고생을 했는데요.
결국 이렇게 SingleObserver를 사용하는 이 생성자에서는 비동기로 처리해야 하는 외부의 함수를 호출한다면 어떻게 해서도 문제가 되는 것 같습니다,, 결국은 아래 결과로 귀결됩니다.
Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure; this is an error in the Swift 6 language mode
# 해결
방법은 생각보다 간단했는데요!
RxSwift에서 이미 해당 케이스에 대한 대응이 되어있었습니다 🥹
Single에서 @escaping () async throws -> T 를 받아서 생성할 수 있는 생성자를 제공해주고 있습니다.
async 함수가 있다면 아래처럼 생성할 수 있습니다.
// Rx func get<T: Decodable>(url: String) -> Single<T> { return Single.create { try await get(url) } }
참고
RxSwift/Documentation/SwiftConcurrency.md at main · ReactiveX/RxSwift
Reactive Programming in Swift. Contribute to ReactiveX/RxSwift development by creating an account on GitHub.
github.com
반응형'Swift' 카테고리의 다른 글
[Swift6] @retroactive 를 써야 할까? Extension declares a conformance of imported type ~ 에 대하여 (0) 2025.04.18 Swift Seqeunce 이해하기 (0) 2025.03.27 [Swift] TaskPriority, Task 우선순위 동작 이해하기 (0) 2025.03.21 [Swift] Sendable 이해하기 (0) 2025.02.11 [Swift] Actor 이해하기 (0) 2025.02.11