Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift 공식 문서] 17. Concurrency (동시성), async, await 본문

swift 공식 문서

[iOS - swift 공식 문서] 17. Concurrency (동시성), async, await

jake-kim 2021. 7. 14. 22:11

* 기초: Sync vs Async vs Serial vs Concurrency 개념

Concurrency

  • Swift는 비동기 및 병렬 코드 진행을 지원
  • Async코드는 일시 중단되었다가 나중에 다시 시작할 수있지만 한 번에 프로그램의 한 부분만을 실행
    • ex) 앱을 일시 중단 후 다시 시작하면 UI업데이트와 같은 작업을 진행하면서 네트워크를 통해 데이터를 가져오는 작업
  • swift에서의 Concurrency: await, async
    • swift가 아닌 다른 언어에서는 Concurrency를 추가하면 디버그가 더 어렵게 만드는 상황이 발생
    • Swift의 언어 수준에서 지원하는 async, await를 사용하면 컴파일 시간에 Concurrency에 관한 문제도 파악 가능

Async 함수 정의 및 호출 (async, await)

  • async, await를 사용하지 않은 경우, async 관련 처리는 closure로 처리
    • 중첩 closure로, 복잡한 코드 형태
listPhotos(inGallery: "Summer Vacation") { photoNames in
    let sortedNames = photoNames.sorted()
    let name = sortedNames[1]
    downloadPhoto(named: name) { photo in
        show(photo)
    }
}
  • async를 사용한 함수 정의: '->'앞에 async 키워드 입력
func listPhotos(inGallery name: String) async -> [String] {
    let result = // ... some asynchronous networking code ...
    return result
}
  • 사용하는 쪽: await키워드 입력
let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[1]
let photo = await downloadPhoto(named: name)
show(photo)
  • 실행 순서
    • 첫번째 줄에서 await 키워드 함수가 호출되는 동안 대기
    • 대기하는 동안 동일한 프로그램의 일부 다른 코드가 동시 실행
    • listPhotos(inGallery:)반환된 후 이 코드는 해당 지점에서 시작하여 다시 실행
  • await에서 대기하는 것을 'thread를 양보(yielding)'한다고 표현

병렬로 Async 함수 호출

  • 병렬이 아닌 async 함수 호출
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)
  • 병렬로 async함수 호출 방법: 'async let' 키워드로 선언
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)

Task와 TaskGroup

  • Task: 프로그램의 일환이고 async로 실행할 수 있는 작업의 단위
  • 각 Task들은 child task들을 갖을 수 있으므로 세부 분류를 위해 TaskGroup 사용
await withTaskGroup(of: Data.self) { taskGroup in
    let photoNames = await listPhotos(inGallery: "Summer Vacation")
    for name in photoNames {
        taskGroup.async { await downloadPhoto(named: name) }
    }
}

Actor

  • Actor는 reference type이며 한 번에 하나의 작업만 변경 가능한 상태에 액세스할 수 있도록 허용
  • 여러 작업의 코드가 actor의 동일한 인스턴스와 상호 작용하는 것에 safe
  • 'class'키워드와 유사하게 actor키워드로 정의
actor TemperatureLogger {
    let label: String
    var measurements: [Int]
    private(set) var max: Int

    init(label: String, measurement: Int) {
        self.label = label
        self.measurements = [measurement]
        self.max = measurement
    }
}
  • actorinstance에 접근할 경우 await 키워드 사용
    • await키워드를 사용하지 않을 경우 compile error 발생
let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)

* 참고

https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html

 

Comments