////
Search
🕛

DispatchQueue

본 글에서는 Swift 기반의 iOS Application에서 Thread(동시성 프로그래밍, 동기/비동기 프로그래밍 등)를 관리하는 방법 중 DispatchQueue에 대해 다룹니다.

1. Main Thread

UI와 관련된 모든 작업은 Main Thread에서 동작하게 됩니다.
Background Thread에서 UI 관련된 작업을 진행하게 될 경우, 아래와 같은 Exception이 발생합니다.
따라서 UI 관련된 작업은 Main Thread에서 진행하는 것이 바람직합니다.
아래는 올바른 예시입니다.
// Distpach Queue - Thread 관리 import UIKit class ViewController: UIViewController { @IBOutlet weak var finishLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() } @IBAction func action(_ sender: Any) { // Main Thread 에서 동작 - UI simpleClosure { DispatchQueue.main.async { self.finishLabel.text = "끝" } } } func simpleClosure(completion: @escaping () -> Void) { // Background Thread 에서 동작 DispatchQueue.global().async { for index in 0..<10 { Thread.sleep(forTimeInterval: 0.2) print(index) } completion() } } }
Swift
복사

2. DispatchGroup

DispatchGroup은 다중 Thread의 큐를 그룹 단위로 묶을 수 있고, Qos(작업 우선 순위)를 부여할 수 있습니다.
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func action(_ sender: Any) { let dispatchGroup = DispatchGroup() let queue1 = DispatchQueue(label: "q1") let queue2 = DispatchQueue(label: "q2") let queue3 = DispatchQueue(label: "q3") queue1.async(group: dispatchGroup, qos: .background) { dispatchGroup.enter() DispatchQueue.global().async(qos: .background) { for index in 100..<120 { Thread.sleep(forTimeInterval: 0.1) print("queue1's internal queue - \(index)") } dispatchGroup.leave() } } queue2.async(group: dispatchGroup, qos: .userInteractive) { for index in 10..<20 { Thread.sleep(forTimeInterval: 0.2) print("queue2 - \(index)") } } queue3.async(group: dispatchGroup) { for index in 20..<30 { Thread.sleep(forTimeInterval: 0.2) print("queue3 - \(index)") } } dispatchGroup.notify(queue: DispatchQueue.main) { print("끝") } } }
Swift
복사

3. 동기 처리(Sync)와 DeadLock(교착 상태)

교착 상태란, Thread가 다음 작업을 진행하지 못하고 계속 대기하고 있는 상태를 말합니다.
sync로 작업 하게 될 경우, 모든 작업을 중지하고 기다리게 됩니다. 따라서 DeadLock이 발생할 확률이 있습니다.
그러므로 굉장히 중요한 작업일 때(해당 작업이 끝나고 다음 작업을 진행해야 할 때) 사용하는 것이 바람직하겠습니다.
또한, Main Thread는 앱이 사용되는 한 계속 작업을 진행하기 때문에 async(비동기)를 사용하는 것이 바람직하겠습니다.
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func action(_ sender: Any) { let queue1 = DispatchQueue(label: "q1") // 다른 작업을 다 멈추게 함 queue1.sync { for index in 10..<20 { Thread.sleep(forTimeInterval: 0.2) print("queue1 - \(index)") } // Dead Lock -> 다음 작업을 진행하지 못하고 계속 기다리고 있는 상태 // Dead Lock이 발생할 수 있기 때문에 sync로 작업 하는 경우는, // 굉장히 중요한 작업일 때(해당 작업이 끝나고 다음 작업을 진행해야 할 때) 사용하는 것이 안전함(많이 사용하지는 않음) // queue1.sync { // for index in 20..<30 { // Thread.sleep(forTimeInterval: 0.2) // print("queue2 - \(index)") // } // } } } }
Swift
복사