Swift - Async Await

JSLee·2022년 5월 23일
0

Async Await

Swift Evolution

사실 async await 기능은 이미 Javascript, kotlin, google-promises 등 다른 언어에서 있는 기능이 Swift 5.5에 들어온 것입니다.

우리는 지금껏 클로져를 통한 completionHandler 를 이용 request/response 메소드를 사용해 왔었습니다.

하지만 completionHanlder 에는 몇가지 문제가 존재 합니다.

  • 콜백 지옥에 빠질수 있다.
  • completion 의 호출없이 return 할수도 있다.

등등 이밖에도 여러 문제가 있습니다.

그래서 개발자들은 항상 여러 문제의 신경을 쓰고 많은 분기 작업 처리가 이어지다 보니
url 에서 data 를 가져오는 메소드들은 항상 코드가 길어지고 가독성이 떨어졌었습니다.

그래서 Swift 5.0 에서 ResultType 을 도입하여 성공 과 실패 두가지를 제공해 주었습니다.
하지만 이도 여러 분기작업이 필요로 했고.. Swift 5.5 에서 이런 문제들을 상쇄해줄 async await 가 추가 되었습니다.

사용

Async Await는 동시성을 지원하지 않습니다. 오로직 비동기만 지원합니다. 사용하기 전
이점을 유의 해야합니다.

비동기함수(async/await)를 사용하면?

  • 비동기 코드를 마치 동기 코드인것 처럼 작성 할 수 있음. ➞ 개발자가 동기 코드에서 사용할 수 있는 동일한 언어 구조를 최대한 활용 가능.

1) 비동기 코드의 성능 향상

2) 코드를 디버깅, 프로파일링 및 탐색하는 동안 보다 일관된 경험을 제공하기 위한 더 나은 도구

3) 작업 우선 순위 및 취소와 같은 동시성 기능을 위한 기반.

( 기존 completion 사용 코드)

( async await 사용 코드)

Async Await 를 사용하여 코드를 비동기적으로 수행할 경우 이처럼 많은 양의 코드가 줄어들게 되고
가독성 또한 향상 되게 됩니다.

async

async 코드는 동시(concurrent) 컨텍스트 에서만 실행 가능합니다. 즉, 다른 async 함수 내 에서, 또는 Task {}를 통해 수동으로 concurrent context를 제공할 때 그 안에서 가능합니다.

또한 error를 반환하게 될경우 async throws 키워드가 되어야 합니다.

따론 completion 에 error 를 담거나 nil 을 통해 호출할 필요없이
error가 발생하면 throws 를 통해 흘려주기만 하면 됩니다.

await

async 함수를 호출하기 위해서는 await 키워드가 필요합니다.

따라서 예시에서 호출하고 있는 URLSession 함수도 async 임을 알 수 있습니다. (iOS 15 부터 async 를 지원하는 여러 API를 선보였는데, 그 중 URL 세션이 포함됩니다)

public func data(from url: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)

중요한건 await 로 마킹된 곳은 potential suspension point(잠재적인 일시 중단 지점)로 지정된다는 것입니다.해당 함수가 대기 상태가 되면, caller 역시 대기 상태가 될 수 있습니다.

Suspend

일시 중단 (suspend) 은 해당 스레드가 다른 동작을 수행할 수 있게 제어권을 놓아주겠다는 의미입니다

  • await로 async 함수를 호출하는 순간, 즉 Suspension point 만나는 순간 해당 스레드 제어권 포기
  • 따라서 async 작업 및 같은 블록에 있는 아래 코드들을 스레드 잡아서 바로 실행 못함
  • 스레드 제어권을 시스템에게 넘기면서, 시스템에게 원래 async 작업도 스케쥴 하라고 함
  • 시스템이 우선순위를 파악함
  • 원래 async 함수가 중요해지는 순간이 왔다고 판단하면 resume
profile
iOS/Android/FE/BE

0개의 댓글