티스토리 뷰

Asynchronous Sequences

이전 섹션의 listPhotos(inGallery:) 함수는 배열의 모든 요소가 준비된 후 전체 배열을 한 번에 비동기식으로 반환합니다.

또 다른 접근 방식은 비동기 시퀀스(asynchronous sequence)를 사용하여 한 번에 하나의 컬렉션 요소를 대기하는 것입니다.

다음은 비동기 시퀀스를 반복(iterating)하는 방법입니다.

import Foundation

let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
    print(line)
}

위의 예는 일반적인 for-in 루프를 사용하는 대신 await for뒤에 씁니다.

비동기 함수 또는 메서드를 호출할 때와 마찬가지로 await는 가능한 일시 중단 지점을 나타냅니다.

대기 루프는 잠재적으로 다음 요소가 사용 가능하기를 기다리는 각 반복의 시작 부분에서 실행을 중단합니다.

 

Sequence 프로토콜을 추가하여 for-in 루프를 사용할 수 있는 것과 마찬가지로, AsyncSequence 프로토콜을 추가하여 for-await-in 루프를 사용할 수 있습니다.

Calling Asynchronous Functions in Parallel

비동기 함수를 await와 함께 호출하면 코드가 한 번에 하나만 실행됩니다.

비동기 코드가 실행되는 동안 호출자는 코드가 완료될 때까지 기다렸다가 다음 코드 행을 실행합니다.

예를 들어 갤러리에서 처음 세 장의 사진을 가져오려면 다음과 같이 downloadPhoto(named:) 함수에 대한 세 번의 호출을 기다릴 수 있습니다.

let firstPhoto = await downloadPhoto(named: photoNames[0])
let secondPhoto = await downloadPhoto(named: photoNames[1])
let thirdPhoto = await downloadPhoto(named: photoNames[2])

let photos = [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

이 접근 방식에는 다음과 같은 중요한 단점이 있습니다.

다운로드가 비동기식이므로 다른 작업이 진행되는 동안에도 downloadPhoto(named:) 는 한 번에 하나만 실행됩니다.

각 사진은 다음 사진 다운로드가 시작되기 전에 완전히 다운로드됩니다.

그러나 각 사진을 개별적으로 다운로드하거나 동시에 다운로드할 수 있으므로 작업을 기다릴 필요가 없습니다.

비동기 함수를 호출하여 주변 코드와 병렬로 실행하려면 상수를 정의할 때 let 앞에 async를 씁니다.

async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])

let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

이 예에서는 이전 호출이 완료될 때까지 기다리지 않고 downloadPhoto(named:) 세 가지 호출이 모두 시작됩니다.

사용 가능한 시스템 리소스가 충분하면 리소스를 동시에 실행할 수 있습니다.

코드가 함수의 결과를 대기하기 위해 일시 중단되지 않기 때문에 이러한 함수 호출 중 어떤 것도 await로 표시되지 않습니다.

대신, photos가 정의된 라인까지 실행이 계속됩니다.

이 시점에서 프로그램은 이러한 비동기 호출의 결과를 필요로 하므로 세 개의 사진이 모두 다운로드될 때까지 실행을 일시 중지하기 위해 await를 작성합니다.

 

다음은 이러한 두 가지 접근 방식의 차이점을 생각해 볼 수 있는 방법입니다.

  • 다음 줄의 코드가 해당 함수의 결과에 따라 달라지는 경우 await를 사용하여 비동기 함수를 호출합니다. 이것은 순차적으로 수행되는 작업을 만듭니다.
  • 코드에서 나중까지 결과가 필요하지 않을 때 async-let 비동기 함수를 호출합니다. 이것은 병렬로 수행될 수 있는 작업을 만듭니다.
  • await  async-let 모두 일시 중단된 동안 다른 코드를 실행할 수 있습니다.
  • 두 경우 모두 가능한 일시 중단 지점을 await로 표시하여 필요한 경우 비동기 함수가 돌아올 때까지 실행이 일시 중지됨을 나타냅니다.

동일한 코드에서 이 두 가지 접근 방식을 혼합할 수도 있습니다.

 

다음글

[iOS] Concurrency(4) - Tasks and Task Groups

댓글
공지사항