Swift 에는 여러 가지의 비동기 처리 방법이 있는데
대표적으로는 DispatchQueue, CompletionHandler, RxSwift, Combine 등이 있다.
지난 WWDC 2021 에서 Async Await 를 발표하였다 기존까지 RxSwift, Combine 이용하고 있어서 늦게 학습 하였지만
상당히 축소되고 알아보기도 쉬워 끄적끄적 해본다..
Async Await 를 본격적으로 알아보기 전에, 현재 어떻게 비동기 처리를 하고 있었는지 알아보도록 하자.
func processImageData1(completionBlock: (_ result: Image) -> Void) {
loadWebResource("dataprofile.txt") { dataResource in
loadWebResource("imagedata.dat") { imageResource in
decodeImage(dataResource, imageResource) { imageTmp in
dewarpAndCleanupImage(imageTmp) { imageResult in
completionBlock(imageResult)
}
}
}
}
}
processImageData1 { image in
display(image)
}
Result 타입이 신규로 나와도 다음과 같이 소스가 길고 복잡하게 나올수 밖에 없다.
func processImageData2c(completionBlock: (Result<Image, Error>) -> Void) {
loadWebResource("dataprofile.txt") { dataResourceResult in
switch dataResourceResult {
case .success(let dataResource):
loadWebResource("imagedata.dat") { imageResourceResult in
switch imageResourceResult {
case .success(let imageResource):
decodeImage(dataResource, imageResource) { imageTmpResult in
switch imageTmpResult {
case .success(let imageTmp):
dewarpAndCleanupImage(imageTmp) { imageResult in
completionBlock(imageResult)
}
case .failure(let error):
completionBlock(.failure(error))
}
}
case .failure(let error):
completionBlock(.failure(error))
}
}
case .failure(let error):
completionBlock(.failure(error))
}
}
}
processImageData2c { result in
switch result {
case .success(let image):
display(image)
case .failure(let error):
display("No image today", error)
}
}
그만큼, 에러 핸들링이 어렵고 개발자가 일일히 로직에 에러 핸들링에 대한 처리를 해줘야한다. 뭐 콜백 지옥이라고도 한다.
자..! 이제 적용 해보자..
위에있는 소스를 async await 를 적용하면 다음과 같이 나온다.
func loadWebResource(_ path: String) async throws -> Resource
func decodeImage(_ r1: Resource, _ r2: Resource) async throws -> Image
func dewarpAndCleanupImage(_ i : Image) async throws -> Image
func processImageData() async throws -> Image {
let dataResource = try await loadWebResource("dataprofile.txt")
let imageResource = try await loadWebResource("imagedata.dat")
let imageTmp = try await decodeImage(dataResource, imageResource)
let imageResult = try await dewarpAndCleanupImage(imageTmp)
return imageResult
}
이렇게만 보면 어려우니까 한줄씩 끊어서 자세하게 보자.
함수 선언부 뒤에 async 가 나온다면 비동기를 뜻한다. 키워드가 섞여서는 안된다 (throws async)(X)
신기하게 호출은 try await 로한다..
func loadWebResource(_ path: String) async throws -> Resource
async 호출을 하기위한 키워드는 앞에 await 를 붙여줘야합니다.
let dataResource = try await loadWebResource("dataprofile.txt")
View
VStack {
View....
}.task {
await 키워드 이용 function 호출
}
ViewModel
func example() {
Task {
await 키워드 이용 function 호출
}
}
Task
비동기 함수를 호출할때 Task 라는 로직 안에 이용해야 합니다. 약간 Android 상에 있는 코루틴과 비슷합니다.
해당 Task 에 속해있는 블록은 백그라운드 영역에서 돕니다
Task 는 옵션을 통해 우선순위를 줄수 있습니다. (high, default, low) 등등....
ex) Task(priority: .high)
마치며
이미 많은 능력자 분들의 블로그 내용도 있지만 내 머릿속의 쏙쏙 넣기위해 작성했는데
작성하면서도 재미있는 기술이 있어 현재 진행중인 Combine 프로젝트에 적용하고 싶은 욕심이 생깁니다.
다음 내용은 Combine -> async await 적용기 적어보도록 하겠슴다
* 아직 내용이 많이 부족하여 공부하면서 계속 수정 하겠습니다!
참고 : https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md
'IOS' 카테고리의 다른 글
iOS - 프로젝트에 SPM 을 달아보자 (0) | 2023.02.19 |
---|---|
Xcode - Google Sheet 에서 다국어 내용 가져오기 (0) | 2023.01.23 |
SwiftUI - List Hide Indicator (0) | 2022.10.23 |
SwiftUI - TextView Attribute (0) | 2022.06.01 |
Swift - Snapkit (0) | 2022.04.10 |