본문 바로가기

학습활동

Swift Concurrency II

비동기 함수를 병렬로 호출

await를 사용하여 비동기 함수를 호출하면 한 번에 하나의 코드만 실행

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가 비동기 작업이어도 프로퍼티에 값을 넣는 동기 작업이 따르기 때문에 동기적으로 작업이 처리됨

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)

→ 비동기 함수를 호출하고 주위 코드와 병렬로 실행되기 위해선, async let을 사용하여 프로퍼티 값을 만드는 동작 전체를 비동기로 처리

 async let과 await은 일시 중단되는 동안 다른 코드를 실행할 수 있음

→ 단, async-await 코드의 결과에 따라 달라지는 경우엔 순차적으로 진행해야하기 때문에, show는 let photos의 값이 생성된 후 동기적으로 실행


Continuation

  • 처리가 완료된 비동기 메서드의 결과를 다시 시작(resuem)할 수 있는 기능
  • Swift에서 높은 수준의 안전한 방법으로 Continuation을 생성, 관리, 재개할 수 있는 기능을 제공함
  • 단, resume은 정확한 곳에서 한번 호출해야함
    • API 비동기 호출을 수동으로 두번 시작하는 경우 모든 경로에서 resume을 호출해야함
    • GCD보다 스위프트 컨커런시가 스레드 관리가 더 효율적이다
    • → API중에서 스위프트 컨커런시를 지원하지 않는 경우 이렇게 감싸서 사용할 수 있다
    • → 특정 상황에서 대리자 API가 여러 번 호출되거나 전혀 호출되지 않는 경우 active continuations을 정확히 한 번 다시 시작하는 것이 중요

Task & Task Groups

Task

  • 프로그램의 일부
  • 비동기적으로 실행할 수 있는 작업 단위
  • Task의 이니셜라이저에 completionHander를 사용하여 동기화 컨텍스트 내부에서 다른 비동기를 호출 가능하게 함
  • 클로저에서 작업을 패키지화하여 다른 스레드에서 즉시 실행 가능하도록 시스템에 보냄
  • 모든 비동기 코드는 Task의 일부로써 실행됨
  •  child Task을 생성할 수 있음
  •  Task Group을 만들고 이에 child Task를 추가할 수 있음
  •  Task Group을 사용하여 우선 순위를 설정하고 작업 취소를 보다 잘 제어할 수 있음
  • → Task를 생성 시 Task의 갯수를 동적으로 지정할 수 있음

Structed Concurrency

  • Task가 명시적인 계층 구조로 정렬되어있음
  • 같은 parent Task를 갖은 Task의 묶음이 Task Group, 각 Task는 child Task를 가질 수 있음
  • 명시적 계층 구조를 갖기 때문에 Swift가 일부 동작을 처리하며 컴파일 타임에서 오류를 감지 가능
// Task Group
await withTaskGroup(of: Data.self) { taskGroup in
		// Task
    let photoNames = await listPhotos(inGallery: "Summer Vacation")
    for name in photoNames {
				// child Task
        taskGroup.addTask { await downloadPhoto(named: name) }
    }
}

Task Group

  • withTaskGroup(of:returning:body:)로 Task Group 생성
  • Task 외부의 Task Group을 사용 금지→ child Task와 같은 동시성 작업에선 mutating한 작업을 수행할 수 없기 때문에, Task Group에서 escaping하는 것을 금지하는 것
  • → Swift는 Task Group에 child Task를 추가하는 것은 mutating한 작업임
728x90

'학습활동' 카테고리의 다른 글

URL Loading System  (0) 2023.11.30
동시성 프로그래밍  (0) 2023.11.08
Swift Concurrency I  (0) 2023.09.28
User Notifications  (0) 2023.09.25
OAuth(Open Authorization)  (0) 2023.09.21