-
Swift 5.5 - async & awaitConcurrency 2021. 9. 25. 11:33
안녕하세요. 그린입니다🟢
이번 포스팅에서는 Swift 5.5에서 새롭게 나온 async & await에 대해 학습해보겠습니다🧑🏻💻
사실 나온지는 Swift 5.5가 나온 3월? 정도지만 이번에 Xcode13으로 업데이트하면서 같이 학습해보게 되었습니다😁
async와 await가 이번 Swift 5.5에서 인기라고 하는데 왜 그런지 알아보겠습니다!
async & await가 간략히 뭘해주나요?
다른 유형의 비동기 처리 작업을 해주는 코드로 비동기 처리 코드를 동기 처리처럼 보일 수 있도록 지원
이전 비동기 처리의 문제
1. 비동기 처리 시 클로저 및 콜백을 통해 비동기 프로그래밍을 하다 보니 복잡도 증가
2. 하나의 비동기 처리 일때는 크게 문제 없지만 여러 비동기 처리와 오류 처리가 섞이면서 많은 중첩이 발생
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) }
3. 위 문제점들로 인해 잦은 실수를 유발
func processImageData4a(completionBlock: (_ result: Image?, _ error: Error?) -> Void) { loadWebResource("dataprofile.txt") { dataResource, error in guard let dataResource = dataResource else { return // <- forgot to call the block } loadWebResource("imagedata.dat") { imageResource, error in guard let imageResource = imageResource else { return // <- forgot to call the block } ... } } }
async & await를 사용하여 해결해보자면
1. 동기 코드 형식의 폼을 보존하며 비동기 처리가 가능 (성능 향상)
2. 코드를 디버깅, 프로파일링 및 탐색하는 동안 보다 일관된 경험을 제공하기 위한 더 나은 도구 (번역이 이렇지만 와닿지가 않음)
3. 작업 우선 순위 및 취소와 같은 미래 동시성 기능을 위한 기반
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 & await 사용
1. async
비동기 작업을 정의하는 키워드로 해당 키워드가 붙으면 비동기적으로 동작한다는걸 알 수 있음
func fetchImages() async throws -> [UIImage] { // .. perform data request }
throws는 async의 위치 표현을 위한것으로 없어도 됨
2. await
비동기 함수 작업의 실행을 동기 시키는 오퍼랜드로 현재 작업 흐름에서 await를 만나면 해당 함수 처리가 끝날때까지 대기시킴
func fetchData() async { do { try await fetchImages() } catch { // .. handle error } }
await는 작업의 블락을 만들기에 async 키워드가 붙은 함수에서만 사용가능
동기 속 비동기 처리
동기 함수속에서 비동기 함수 처리를 해야할 경우 아래와 같이 Task 함수 클로저와 await를 통해 구현해줄 수 있다.
func fetchData() { ... Task { do { try? await fetchImages() } catch { // .. Handle error } } }
Task 함수 자체가 async로 마크되었기에 가능
요약
이렇게 간단하게? 음.. 전달하고자 하는 바는 간단하지 않겠지만 복잡하게 들어가면 한도 끝도 없을것 같아 간단하게 이해해버렸다..😱
기존에 너무 복잡하게 쓰던 비동기 처리 작업을 바꿔놨지만 내부적으로는 복잡하게 처리되있겠지!? 그렇지만 표면적으로 보고 쓰기엔
확실히 동기 코드처럼 접근하고 이해할 수 있으니 한결 비동기 처리가 편해졌다고 생각한다.
아직 실무 코드에서 적용을 못했는데 앞으로 나올 비동기 처리에 대해 요런식으로 활용한다면 코드 복잡성과 가독성을 높아질것 같다👍🏻[참고자료]
https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md
https://www.avanderlee.com/swift/async-await/
'Concurrency' 카테고리의 다른 글
Swift Concurrency - Parallel (4) 2023.03.06 Swift Concurrency - Task (4) (8) 2023.03.02 Swift Concurrency - Task (3) (4) 2023.03.02 Swift Concurrency - Task (2) (2) 2023.02.27 Swift Concurrency - Task (1) (6) 2023.02.24