참고 자료
Apple 공식 문서 Concurrency Programming Guide
목차 (눌러서 이동)
비동기 프로그래밍, Grand Central Dispatch(GCD)
Apple 의 UI 는 Main thread 에서만 업데이트 되도록 디자인되어 있다. UIKit 가 thread-safe 하지 않아 Main thread 에서 순차적으로 처리하는 것이 안정적이기 때문이다. (UIKit 가 thread-safe 하지 않은 이유.)
Main thread 가 UI 를 업데이트 할 동안 네트워킹과 같은 무거운 작업들을 다른 thread 에서 동시에 작업할 수 있다면 앱 성능 향상에 효과적일 것이다. 이것이 비동기 프로그래밍이 필요한 이유이다.
Apple system 에서는 비동기 프로그래밍을 위해 GCD 를 사용한다. GCD 는 멀티코어 하드웨어에서 다수의 code block 을 동시 실행하도록 지원하는 Framework 이다.
비동기 프로그래밍을 위해 GCD 를 사용한다는 것은 비동기적으로 처리하고 싶은 code block(task) 을 DispatchQueue 에 push 한다는 의미이다. 비동기 작업을 DispatchQueue 에게 맡기기만 하면 알아서 효율적으로 처리하기 때문에 개발자가 threading 에 관여할 필요가 없어진다.
DispatchQueue
비동기적 수행을 위해 push 된 task 들을 관리하고 처리하는 객체이다. 시스템의 가용한 자원에 따라 thread 의 생성과 사용을 관리하여 적절한 thread 가 task 들을 처리하도록 한다. Queue 의 종류로는 Serial queue, Concurrent queue, Main dispatch queue 가 있다.
DispatchQueue types
Serial queue 는 Private dispatch queue 라고도 불리며 한 번에 하나씩 push 된 순서대로 작업을 수행한다. 때문에 특정 자원에 대한 접근을 통제할 때 자주 사용된다. 필요한 만큼 생성할 수 있으며 헷갈리지 말아야 할 것은 하나의 Serial queue 내의 작업들을 순차적으로 수행한다는 것이지 서로 다른 Serial queue 들의 작업들은 동시에 수행될 수도 있다는 점이다.
let serialQueue = DispatchQueue(label: "serial")
Concurrent queue 는 Global dispatch queue 라고도 불리며 하나 이상의 작업을 동시에 수행할 수 있다. (push 된 순서대로 수행되는 것은 동일.) Private dispatch queue 에도 option 을 주어 concurrent 하게 수행하는 queue 를 생성할 수 있지만 특별한 이유가 없다면 시스템에서 미리 정의하는 Global dispatch queue 를 사용하는 것이 권장된다.
// It's possible to create a private concurrent dispatch queue.
let concurrentQueue = DispatchQueue(label: "concurrent", attributes: [.concurrent])
// But predefined global dispatch queue is recommended.
let concurrentQueue = DispatchQueue.global(qos: .default)
Main dispatch queue 는 전역적으로 사용 가능한 serial queue (작업을 순차적으로 처리.) 이고, 앱의 Main thread 에 작업을 수행시킨다.
Queueing options (sync or async)
DispatchQueue 에 작업을 push 할 때 두 가지 방식으로 scheduling 할 수 있다.
Synchronous 하게 push 하면 code block 이 완료될 때까지 기다린다.
DispatchQueue.global(qos: .default).sync { /* task */ }
Asynchronous 하게 push 하면 하던 작업을 계속 진행하면서 다른 어딘가 에서 task 가 동시에 수행된다.
DispatchQueue.global(qos: .default).async { /* task */ }
Code Example
온라인 이미지를 다운로드 받아 UI 에 적용한다고 하자. 이미지 다운로드와 같은 시간이 걸리는 작업은 Global queue 를 사용하고 UI 업데이트는 Main queue 를 사용하므로 다음과 같이 처리할 수 있다.
// You want your app to prepare the other things while
// setting up the image. So, push this task to the
// global queue asynchronously.
DispatchQueue.global(qos: .userInteractive).async {
// Download image from the online.
let image = downloadImage()
// UI update should be execute on the main queue.
DispatchQueue.main.async {
updateUI(image: image)
}
}
'iOS 개발 > App 개발 관련' 카테고리의 다른 글
[iOS] AppDelegate, SceneDelegate 의 역할, WWDC2019 (iOS 13~) (0) | 2021.10.29 |
---|---|
[iOS] Stanford iOS Lecture - MVVM (cs193p) (0) | 2021.08.31 |
[iOS] 모의 URLSession 으로 네트워킹 Test 하기 (0) | 2021.07.30 |
[iOS] TDD(Test Driven Development) Tutorial (0) | 2021.07.16 |
[iOS] WWDC 2019 Testing in Xcode (0) | 2021.07.12 |