본문 바로가기
iOS/Concurrency

Async Await

by 지금갑시다 2022. 12. 3.

 네트워크와 통신을 하며, 서버에서 가져오는 데이터들을 사용자들의 불편함 없이 앱에 잘 보여주기 위해서는 비동기처리가 필수이고 매우 중요하다고 생각한다.

 때문에, Concurrency 공부를 시작한다!

 

Async Await는 기존의 Completion handler인 @escaping closure의 불편함을 개선하기 위해 Swift5.5 버전에서 업데이트 되었다고 한다.

 

@escaping closure의 불편함으로는,

1. 한번 실행될 때마다 들여쓰기가 되어 안에서 분기 처리가 되면 가독성이 떨어지게 됨

2. 코드만 보고는 해당 줄이 비동기 처리가 되고 있는 코드인지 잘 알 수 없음

3. @escaping closure의 parameter syntax(@escaping(String) -> ())가 어려움

 

REF: https://www.hackingwithswift.com/articles/233/whats-new-in-swift-5-5

 

그럼 이제 주인공인 Async Await 는 어떻게 위의 불편함을 해소했는지와, 실 사용 예시들을 보며 이해를 해보자!

 

func fetchTitle() async -> String {
    return "Title"
}

let title: String = await fetchTitle()

가장 쉬운 예시로 async의 예시를 보자면, 함수명 뒤에 붙어 해당 함수가 Async하게 실행됨을 명시적으로 표시해주게 된다.

await을 쓰게 되는 예시에서도 , async가 명시되어 있는 함수를 쓰게 된다면, 이 함수를 실행할 때 await를 붙여주어야 한다.

 

그리고 await는 fetchTitle()의 함수가 끝나고, title에 값이 들어가게 되는 것을 보장한다.

예시로,

 

func fetchTitle() async -> String {
    return "Title"
}

let title: String = await fetchTitle()
print("title is what?")

바로 위의 코드에서 print문은 절대로! 바로 윗줄의 fetchTitle()이 완료될 때까지 실행되지 않는다.

 

조금 더 생각해서, 서버에서 이미지를 불러오는 함수가 fetchTitle()이라고 생각하고 아래 print문이 그 가져온 이미지에 따른 반응형 코드라고 생각해보자!

그렇다면, print문은 이미지가 불려오고 나서 실행되어야 하지 않을까?

때문에, await으로 fetchTitle의 함수 실행완료를 보장하고, print를 정상적으로 실행되게 해준다.

 

위의 함수를 @escaping closure로 만들어보자.

func fetchTitle(completion: @escaping(String) -> ()) {
    completion("Title")
}

var title: String = ""

fetchTitle { title in
    self.title = title
}

print("title is what?")

사실 복잡한 예시들이 아니라 이해하기 어렵지 않지만,

위의 @escaping closure과는 다르게 Async Await를 썻을때, 해당 라인의 종료됨을 보장하고, 기존의 문법에 async await만 붙이면 되는 장점과 여러개의 비동기처리가 이루어 질때, 훨신 가독성에서 좋다. 아래 코드를 보면, 피라미드 형식으로 쌓이는 closure 보다 indent가 들어가지 않고 await만 있는 예시가 읽기 좋은 것을 확인할 수 있다.

func fetchTitle(completion: @escaping(String) -> ()) {
    completion("Title")
}

func fetchTitle2(completion: @escaping(String) -> ()) {
    completion("Title")
}

var title: String = ""

fetchTitle { title in
    fetchTitle2 { title in
        self.title = title
    }
}
func fetchTitle() async -> String {
    return "Title"
}

func fetchTitle2() async -> String {
    return "Title"
}

let title: String = await fetchTitle()
let title2: String = await fetchTitle2()

 

Async Await 사용법 끗!