-
Swift Concurrency - 이전 버전에서 비동기 시스템 API 사용하기Concurrency 2023. 3. 16. 13:54
안녕하세요. 그린입니다🍏
이번 포스팅에서는 비동기 시스템 API를 이전 버전에서 사용할 수 있도록 구현하는 학습을 해보겠습니다🙌
Swift Concurrency가 iOS 13부터 사용이 가능하게 나왔어도 계속 디벨롭을 거쳐 왔습니다. (당연하지만!?)
그렇기에 오늘 예시로 들어볼 iOS 15 이상에서 URLSession 네트워킹에서 편하게 async/await를 사용할 수 있지만 그 하위 버전인 iOS 13, 14대에서는 직접 사용하지 못하는 불편함이 있었어요😭
이전 포스팅에서도 잠깐 나왔는데 Swift 5.5 부터 비로소 기존 코드에서도 비동기 처리를 할 수 있게 변화했다고 했죠?
즉 Xcode 13.2부터 호환이 되지만 그 기준이 OS로는 iOS 15, macOS Monterey입니다.
그래서 오늘 iOS 15 미만에서도 비동기 시스템 API를 사용할 수 있도록 이전 버전 대응을 해볼께요🎉
iOS 15 미만에서 비동기로 URLSession 네트워킹 하기
자 우선 iOS 15 이상에서는 아래와 같이 session의 data 통신을 비동기로 할 수 있습니다.
struct ModelLoader<Model: Decodable> { var session = URLSession.shared var decoder = JSONDecoder() func loadModel(from url: URL) async throws -> Model { let (data, _) = try await session.data(from: url) let model = try decoder.decode(Model.self, from: data) return model } }
그렇지만, 만약 iOS 15 미만에서 동일하게 사용한다면 아래와 같은 에러 문구를 만날 수 있습니다.
// Error: 'data(from:delegate:)' is only available in iOS 15.0 or newer
즉, iOS 15에서 data(from:delegate:) 메서드가 비동기로 처리되도록 하는것이 생겼다고 볼 수 있죠.
그렇지만, 우리의 미니멈 타겟은 15 이상이 아닐 경우가 많으니 대응을 해봐야겠습니다!
기존 프로젝트 코드에서 URLSession 네트워킹에 async,await인 Swift Concurrency를 붙이고 싶다입니다🥸
자 그럼 우선 URLSession을 확장하여 구현해볼께요.
@available(iOS, deprecated: 15.0, message: "Use the built-in API instead") extension URLSession { func data(from url: URL) async throws -> (Data, URLResponse) { try await withCheckedThrowingContinuation { continuation in let task = self.dataTask(with: url) { data, response, error in guard let data = data, let response = response else { let error = error ?? URLError(.badServerResponse) return continuation.resume(throwing: error) } continuation.resume(returning: (data, response)) } task.resume() } } }
먼저 iOS 15 미만에서만 사용하고 이상에서 사용 시 디프리케이트 되었다는걸 안내해주도록 하죠!
이유는 동일한 data 메서드인데 iOS 15이상에서 사용 시 기본 제공해주는걸 사용할 수 있도록 배려하기 위함입니다.
보시면 data 메서드를 async하게 만들어 비동기 호출임을 명시해줍니다.
withCheckedThrowingContinuation으로 만들어요.
이전에 다뤄봤던 continuation 개념이라고 생각하면 쉽습니다🙋🏻
내부에서 실제로 통신 중 에러가 나지 않고 정상적인 data가 들어온다면 continuation의 resume으로 반환해줍니다.
이게 다에요!!!
이걸 다뤄보면서 핵심은 URLSession뿐 아니라 하위 버전에서 아직 제공하지 않는 비동기 시스템 API를 이런식으로 확장하여 만들고 사용할 수 있습니다.
물론 Swift Concurrency 자체가 iOS 13 이상에서 제공되기에 그 미만 버전의 지원은 불가합니다🥊
마무리
실제로 이런 구현을 통해 많이 사용할지는 아직 다뤄보지 못했지만 충분히 기존 프로젝트 코드에서 호환할 수 있게 사용할 수 있을것 같습니다.
[참고 자료]
https://www.swiftbysundell.com/articles/making-async-system-apis-backward-compatible/
'Concurrency' 카테고리의 다른 글
Swift Concurrency - @MainActor 사용하기 (8) 2023.03.27 Swift Concurrency - Actor (8) 2023.03.20 Swift Concurrency - Throwing & 비동기 Swift 프로퍼티 (5) 2023.03.14 Swift Concurrency - Async sequence & stream (9) 2023.03.09 Swift Concurrency - map & forEach (14) 2023.03.09