기초탄탄/Swift

GCD (Grand Central Dispatch) 를 그려보기

노랑✨ 2025. 1. 20. 17:32

오늘은 GCD(Grand Central Dispatch) 에 대해서 정리해보려고 합니다. 예전 게시글 https://norang0.tistory.com/8 에서 해당 개념을 살펴봤을때는 DispatchQueue 를 기차 선로에 빗대서 각각의 작업흐름을 생각해봤는데, 이번에는 비유보다는 동작 자체의 흐름을 다시 그려보려고 합니다.

흐름을 제어하는 Dispatch

구체적으로는 DispatchQueue.main 과 DispatchQueue.global(), 그리고 sync 와 async 의 조합을 살펴보려고 합니다. 글자 그대로의 의미부터 살펴보자면 아래처럼 이해하면 될 것 같습니다.

DispatchQueue.main : 메인 스레드에 디스패치
DispatchQueue.global() : 글로벌 스레드* 에 디스패치
sync : 동기, 직렬
async : 비동기, 병렬

* 구분상 global thread 이라고 표현했지만, 실질적으로는 main thread 이외의 thread 들이라고 생각하면 좋을듯 합니다.

 

각 용법을 조합하면 아래와 같은 해석(?)이 될 것 같습니다.

DispatchQueue.main.sync (태스크를) 메인 스레드(Serial)에 동기로 디스패치하겠다
DispatchQueue.main.async (태스크를) 메인 스레드(Serial)에 비동기로 디스패치하겠다
DispatchQueue.global().sync (태스크를) 메인 이외의 스레드(Concurrent)에 동기로 디스패치하겠다
DispatchQueue.global().async (태스크를) 메인 이외의 스레드(Concurrent)에 비동기로 디스패치하겠다

 

알록달록하긴 한데,, 이렇게 적어놓기만 해서는 이해가 쉽게 되지 않아서 그림으로 그려보려고 합니다. 먼저 작업대기열을 그려보겠습니다. 메인에 태스크를 5개 정도 주겠습니다.

 

DispatchQueue.main.sync (태스크를) 메인 스레드에 동기로 디스패치하겠다

1. 코드의 태스크 2개를 디스패치 구문에 넣었다고 해보겠습니다. 메인스레드에게 동기로 디스패치.

2. 메인스레드는 Dispatch 된 Task 1 과 Task 2 가 끝나길 기다리고 있습니다. 동기처리되어 있기 때문에 다시 움직이려면 1,2 가 끝나야 하거든요. 

3. 그런데 Task 1 과 Task 2 가 다시 메인스레드에게 돌아옵니다. 메인스레드는 이 태스크들이 완료되어야 움직일 수 있어서 또 기다립니다.

4. 그렇게 아무도 처리하지 않는 Task 1, Task 2 가 남고... 앱은 무한 대기 상태에 빠지고 DeadLock 이 발생할 수 있습니다.

 

DispatchQueue.main.async (태스크를) 메인 스레드에 비동기로 디스패치하겠다

1. 이번에는 비동기로 디스패치 하겠습니다. 메인 스레드는 해당 태스크가 끝나길 기다리지 않아도 됩니다. 그래서 Task 3 부터 처리합니다.

2. 비동기로 디스패치 된 태스크들은 메인 스레드의 큐에 추가됩니다.

3. 메인스레드는 가지고 있던 태스크들을 모두 처리하고 할당되어 있는 Task 1, Task 2 도 마저 처리합니다.

 

DispatchQueue.global().sync (태스크를) 메인 이외의 스레드에 동기로 디스패치하겠다

1. 이번에는 global 을 이용해서 메인 이외의 스레드에게 디스패치 하겠습니다. 하지만 이번에도 동기로 처리되어 메인은 Task 1, Task 2 가 완료될때까지 기다립니다.

2. 메인 이외의 스레드가 해당 Task 1, Task 2 를 처리합니다 (*코드상으로는 그렇지만 실제 메모리 처리로는 메인이 합니다;;)

3. Task 1, Task2 가 끝나고, 메인이 Task 3 부터 다시 작업을 시작합니다.

main 이 그냥 혼자 다 처리하는거랑 다를게 없다.

 

DispatchQueue.global().async (태스크를) 메인 이외의 스레드에 비동기로 디스패치하겠다

1. global 스레드에게 비동기로 디스패치 합니다. 메인은 Task 1, Task 2 종료까지 기다리지 않아도 됩니다.

2. 메인스레드와 global 스레드가 각자의 일을 갖고 동시에 일을 합니다. 드디어 동시성을 활용할 수 있는 방안이네요.

 

 

DispatchQueue 활용에는 여러 옵션이 있고 방법들이 있지만 가장 기본적인 조합은 위 네가지가 아닐까 생각해봅니다. 그런데 그 중에도 sync 는 딱히 쓸 일이 없을 것 같고.... main.async 로 메인스레드의 작업 순서를 조절하거나, global().async 로 네트워크 처리 등 긴 시간이 소요될 것 같은 태스크를 메인에서 덜어내어 병렬처리 하는 정도로 사용할 수 있을 것 같네요. 추후 네트워크를 이용한 기능을 구현하는데에 활용해보면 좋겠습니다!

저한테도 스레드가 한 대여섯개 달려있어서 여러가지 일을 병렬적으로 처리하고 싶다는 생각을 하며 (헤르미온느??) 글을 마무리해봅니다. 그럼 안녕!