XLOG

[Swift] Async/await 의 이해 본문

Swift/Etc

[Swift] Async/await 의 이해

X_PROFIT 2023. 2. 18. 00:49

Async/await 은 concurrency programming 을 위한 swift 5.5 에 나온 기능이다.

기존에는 비동기 프로그래밍을 위해 GCD를 사용하며 completion handler를 많이 사용했다.

 

하지만 여기에 큰 문제점이 있다. thread explosion, deadlock, 가독성 등

개발자들은 조금 더 쉽고 안전하게 비동기프로그래밍을 하길 원한다. 그래서 채택하게 된 것이 async/await 이다.

 

 

우선 wwdc 영상에 나온 예시 코드를 먼저 살펴보자.

우선 위에 코드는 기존 completion handler 를 사용한 방법이다.

wwdc21 Meet async/await in Swift 영상에서 나온 코드인데, 설명 중에 guard let ~ else { return } 구문에서 두 번정도 에러 핸들링을 해주지 않고 넘어간다. 그렇게 되면 문제가 발생할 경우 main thread 에 에러 발생을 알리지 않게 되고 ui 업데이트는 진행되지 않는 문제를 발생시킬 수 있다고 안내를  하고 있다. 

 

하지만 async await 를 사용하게 되면 우선 코드가 짧아지고 가독성이 좋아진다. 

가독성에 대한 문제는 해결이 되었지만 thread explosion 은 어떻게 해결을 했을까?

 

이건 WWDC21 Swift concurrency: Behind the scenes 과 기타 블로그 글을 참고했다.

async 함수에서 await 구문을 만나게 되면 suspension point 를 생성하고 스레드 제어권을 System 에 넘겨주게 된다. 그렇게 하나의 Task 에서 다음 작업을 진행하면서 suspension 된 작업들이 필요한 시점이 생기면 시스템은 resume 하여 작업을 이어간다.

 

Thread 를 새로 생성에서 다음 작업을 이어가는 것이 아니기 때문에 과도한 context switching 도 방지할 수 있으며 기존 GCD 의 문제점을 많이 보완하였다.

 

이것이 가능한 이유는 Thread 는 모두 독립된 stack, heap 영역을 갖는다. heap 영역에 suspend 된 함수에 내용을 저장하여 필요한 상황에 stack 메모리의 프레임을 바꿔줌으로서 새로운 thread 생성이 없이도 비동기 프로그래밍을 가능하게 한다.

 

이것은 coroutine model 을 기반으로 Swift Concurrency 가 구성되어 졌기에 스레드에 국한되지 않고 동시성 프로그래밍 환경을 제공할 수 있기 때문이라고 한다. 

 

사용법은 예제 코드에 나온 것 처럼 함수에 async 를 명시해 주면 된다. 에러 핸들링을 위해 throws 와 같이 사용을 할 경우에는 무조건 throws 앞에 async 를 명시해 줘야 한다. 만약 순서가 바뀌게 되면 throws 는 작동을 하지 않는다고 한다.

 

그 후 suspend 할 작업 앞에 await 을 명시해주면 된다.