Swift의 비동기 메소드를 async/await 메소드로 변환하기
Swift 5.5는 비동기 프로그래밍을 간소화하는 새로운 기능을 도입했는데, 그 중 하나가 async/await 패턴입니다.
이 패턴을 사용하면 비동기 코드를 알기 쉽고 깔끔하게 작성할 수 있습니다. 하지만 이미 작성된 비동기 메소드를 새로운 async/await 메소드로 변환해야 할 때가 있습니다.
예를 들어, 아래와 같은 비동기 메서드가 있다고 가정합니다.
이 코드를 수정할 수 없다면,
어떻게 async/await 메서드에서 이 메서드를 호출할 수 있을까요?
func download(url: URL, completionHandler: @escaping (Result<Data, Error>) -> Void) {
let task = URLSession.shared.dataTask(with: url) { data, _, error in
if let data = data {
completionHandler(.success(data))
} else if let error = error {
completionHandler(.failure(error))
} else {
fatalError("Should be impossible to get here")
}
}
task.resume()
}
이럴 때는 withUnsafeContinuation
및 withUnsafeThrowingContinuation
메서드를 활용하면 됩니다.
Swift의 withUnsafeContinuation
메서드는 비동기 작업의 결과를 반환하는 데 사용됩니다. 이 메서드는 비동기 작업을 수행하고, 결과를 continuation 객체를 통해 반환합니다. 예를 들어, 아래의 코드는 withUnsafeContinuation
을 사용하여 비동기 작업을 수행하고 그 결과를 반환하고 있습니다.
1. withUnsafeContinuation(_:)
func withUnsafeContinuationMethod() async -> Result<Data, Error> {
return await withUnsafeContinuation { continuation in
download(url: URL(string: "https//www.example.url")!) { result in
continuation.resume(returning: result)
}
}
}
위 코드에서 withUnsafeContinuation
메서드를 사용하여 비동기 작업을 수행하고 결과를 반환하고 있습니다. 이를 통해 기존의 비동기 작업을 async/await 메소드로 변환할 수 있습니다.
비동기 작업을 수행하는 동안 에러가 발생할 수 있는 경우에는 withUnsafeThrowingContinuation
메서드를 사용하면 됩니다. 이 메서드는 비동기 작업을 수행하고, 발생하는 에러를 처리하는 데 사용됩니다. 아래의 코드는 withUnsafeThrowingContinuation
을 사용하여 비동기 작업 중 발생하는 에러를 처리하고 있습니다.
2. withUnsafeThrowingContinuation(_:)
func myAsyncThrowingMethod() async throws -> String {
return try await withUnsafeThrowingContinuation { continuation in
// 비동기 작업 수행
DispatchQueue.global().async {
if let result = performTask() {
continuation.resume(returning: result)
} else {
continuation.resume(throwing: MyError.someError)
}
}
}
}
위 코드에서 withUnsafeThrowingContinuation
메서드를 사용하여 에러를 던질 수 있는 비동기 작업을 처리하고 있습니다. 이를 통해 비동기 작업 중 발생하는 에러를 async/await 메소드로 처리할 수 있습니다.
이 두 메서드를 사용하면 기존의 비동기 메소드를 async/await 메소드로 쉽게 변환할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 향상시키며, Swift의 새로운 동시성 기능을 최대한 활용할 수 있습니다. 또한, 이를 통해 Swift에서 비동기 작업을 보다 효율적으로 처리할 수 있게 됩니다.
비동기 메소드 변환의 중요성
Swift에서 비동기 메소드를 async/await 메소드로 변환하는 것은 코드의 가독성을 높이는 데 기여하며, 이는 코드 유지 보수의 중요한 요소입니다. 비동기 작업을 수행하는 코드는 복잡하고 이해하기 어려울 수 있는데, async/await 패턴을 사용하면 코드를 단순화하고 이해하기 쉽게 만들 수 있습니다.
또한, 비동기 메소드를 async/await 메소드로 변환하는 것은 Swift의 새로운 동시성 기능을 최대한 활용하는 데 도움이 됩니다. 이 기능을 활용하면, 앱의 성능을 향상시키고 사용자 경험을 개선할 수 있습니다.
변환 과정에서의 주의점
비동기 메소드를 async/await 메소드로 변환하는 과정에서는 주의가 필요합니다. withUnsafeContinuation
와 withUnsafeThrowingContinuation
메서드는 각각 비동기 작업의 결과를 반환하고, 발생하는 에러를 처리하는 데 사용되지만, 이 메서드들은 "unsafe"
라는 이름에서 알 수 있듯이, 사용에 주의가 필요합니다.
withUnsafeContinuation
withUnsafeContinuation
메소드는 비동기 작업의 결과를 반환하는 데 사용됩니다. 이 메소드를 사용하면 비동기 작업을 수행하고, 그 결과를 continuation 객체를 통해 반환할 수 있습니다. 하지만 'unsafe'
라는 이름에서 알 수 있듯이, 이 메소드는 사용에 주의가 필요합니다.
continuation 객체를 정확히 한 번만 재개
해야 하며, 이를 지키지 않으면 예기치 못한 동작이나 앱의 충돌을 초래할 수 있습니다.
func withUnsafeContinuationMethod() async -> Result<Data, Error> {
return await withUnsafeContinuation { continuation in
download(url: URL(string: "https//www.example.url")!) { result in
continuation.resume(returning: result)
continuation.resume(returning: result) // 에러 발생 예정
}
}
}
위 코드에서는 continuation이 두 번 호출됩니다.
컴파일러는 이러한 위험에 대해 경고하지 않습니다. 그러나 빌드를 통해 코드를 실행하면
위의 이미지처럼 오류에 직면하게 됩니다.
실제 프로젝트에서 이런 오류가 발생하면, 개발자는 오류가 어디에서 발생했는지 파악하기 어렵습니다.
이런 문제를 방지하기 위해 withCheckedContinuation
메소드를 사용할 수 있습니다.
withCheckedContinuation
withCheckedContinuation
메소드는 withUnsafeContinuation
의 안전한 버전으로, 동일한 기능을 제공하지만 continuation 객체가 정확히 한 번만 재개되는지 확인합니다. 이를 통해 프로그래머의 실수로 continuation 객체가 여러 번 재개되거나 재개되지 않는 경우를 방지할 수 있습니다.
func withCheckedContinuationMethod() async -> Result<Data, Error> {
return await withCheckedContinuation { continuation in
download(url: URL(string: "https//www.example.url")!) { result in
continuation.resume(returning: result)
continuation.resume(returning: result) // 에러 발생 예정
}
}
}
위 코드에도 마찬가지로 컴파일러는 위험에 대해 경고하지 않습니다. 그러나 빌드를 통해 코드를 실행하면
Thread 2: Fatal error: SWIFT TASK CONTINUATION MISUSE: withCheckedContinuationMethod() tried to resume its continuation more than once,
위와 같은 오류를 해당 코드에서 발생했다고 상세하게 알려줍니다.
위의 코드에서 발생한 오류에 대해 자세히 상세하게 알려주게 됩니다. 이를 통해 개발자는 디버깅을 수월하게 할 수 있게 됩니다.
물론, withCheckedContinuation
메서드는 withUnsafeContinuation
에 비해 오버헤드를 발생시키므로 성능 측면에서는 withUnsafeContinuation
이 더 좋을 수 있습니다. 그러나 유지보수 측면에서는 withCheckedContinuation
메서드를 사용하는 것이 좋을 수 있습니다.
마치며
withUnsafeContinuation
및 withUnsafeThrowingContinuation
메서드를 활용하면 기존의 비동기 메소드를 async/await 메소드로 쉽게 변환할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 향상시키며, Swift의 새로운 동시성 기능을 최대한 활용할 수 있습니다.
이러한 방법을 통해 Swift에서 비동기 작업을 보다 효율적으로 처리할 수 있습니다.
Uploaded by