드디어 무섭기도 하고, 어렵기도 해서.... 미루고 미뤄왔던.. GCD 차례입니다.
GCD?
제가 이해한 순서대로 글을 좀 적어볼게요
1. 우선 GCD란 멀티 스레드 환경에서 편리하게 개발할 수 있도록 해주는 기술 (설명이 부족해..)
2. 이 말이 무슨 말이냐면, 해야할 일이 많아진 경우에 알아서 일을 분배해주고, 일할 쓰레드가 부족하면 알아서 늘려주는 기술
3. 기본적으로 작업은 메인 스레드에만 할당되어 있는데, 메인스레드도 일을 하고 다른 스레드들 역시 일을 하도록 만듦. (동시성 프로그래밍) > 비동기 작업
4. 개발자는 QUEUE라는 곳에 어떤 작업을 진행할지 코드를 넣어주기만 하면 되고, 일의 분배나 스레드 관리는 신경쓰지 않아도 됨.
저는 위 순서대로 GCD 개념을 익혔는데요, 음 확실히 1단계에서 4단계로 갈수록 이해가 좀 되는 느낌이었어요.
그런데 과연 이게 다일까요? 아니겠죠 😂
조금 더 살펴보겠습니다.
DispatchQueue
위 4번의 QUEUE가 바로 이 DispatchQueue인데요, 이 친구는 global, main, custom 이렇게 세 가지로 나누어집니다.
우선 DispatchQueue.global()의 경우
- Concurrent Queue가 기본이고
- 작업을 여러 쓰레드에 나눠서 보냅니다.
여기서 Concurrent Queue가 기본적이라 함은 큐에 추가된 작업이 동시에 여러개의 쓰레드에서 병렬적으로 실행되는 것입니다.
일하는 사람이 4명이라 하면, 4명이 모두 일하는 경우가 되겠죠?
반면 DispatchQueue.main 은
- Serial Queue가 기본이고
- 하나의 스레드(Main)에서 처리
- 특히, UI업데이트시, 무조건 main에서 처리합니다.
여기서 Serial Queue라 함은 Concurrent Queue와 반대입니다. 무조건 큐에 추가된 작업이 한 번에 하나씩 순차적으로 실행됩니다.
이전 작업이 끝나지 않으면? 다음 작업을 실행하지 않는 것이에요.
Async / Sync
동기(Sync)
- 메인스레드에서 일을 순서대로 처리
- 큐에 들어간 작업이 끝날 때까지 기다렸다가 다음 작업 실행
비동기(Async)
- 메인스레드에서만 일처리 X, 다른 스레드로 일처리를 맡기고 그 일에대해 신경쓰지 않음.
- 큐에 작업을 보내놓음
Serial / Concurrent
직렬(Serial) - Main
- 큐에 들어온 작업을 하나의 메인 스레드에서만 처리
동시(Concurrent) - Serial
- 큐에 들어온 작업을 여러 스레드에 분산하여 처리
여기까지 봤을 때 조금 헷갈리는 부분이 있더라구요
그래서 다시 정리를 해보면
- 동기, 비동기는 작업을 큐에 보내놓고 작업결과를 기다릴지 말지에 대한 것이고,
- Serial, Concurrent는 큐에 들어온 작업을 다수의 쓰레드 or 메인 쓰레드로 처리할지 정하는 것입니다.
그림으로 보면 대충 이런 느낌입니다 (ㅋㅋㅋㅋㅋㅋ 그림이 ㅎㅎ 좀)
확실하게 동기, 비동기와 serial 과 concurrent가 맡은바가 다르죠? 저는 처음에 다 비슷한 역할을 하는 애들인 줄 알았어요..
하지만 이제는 기능이 확실히 다르다는 것을 알게되었죠 😝
그렇다면 이들을 조합할 수 있는 케이스가 총 4가지가 나오는데요
(serial + async, serial + sync, concurrent + async, concurrent + sync)
이 중에서 제가 좀 오호~ 했던 친구들 두 친구를 소개해볼까해요.
우선 첫번째는 Serial + Sync의 조합이에요
이때 어떤일이 일어나냐면 만약 메인 쓰레드가 Sync이기 때문에 큐에다가 작업을 주고 끝날때까지 기다릴게~ 합니다.
그런데 serial이기에 큐가 받은 일을 하나의 쓰레드에 몰아주게 되겠죠?
다른 쓰레드로 일이 가면 문제가 없겠지만 메인쓰레드로 간다면 어떻게 될까요?
분명 메인쓰레드는 이전 작업이 끝날때까지 기다리겠다고 선언했지만, 큐가 메인쓰레드로 다시 일을 보내버린겁니다.
이전 작업이 끝나지 않았기 때문에 메인쓰레드는 일을 하지 않겠죠?
이 상황을 우리는 교착상태(Dead Lock)이라고합니다.
두번째는 Concurrent + Sync 의 조합입니다.
이 역시도 출발은 메인쓰레드에서 해볼게요.
Sync이기 때문에 작업을 주고 끝날때까지 메인쓰레드는 기다릴겁니다.
Concurrent이기 때문에 일을 여러군데로 분산은 하겠죠? 분산된 상황에서 Sync이기에 메인쓰레드는 2번 쓰레드로 보낸일이 끝날때까지 다른일을 못합니다. 3번쓰레드 역시 마찬가지 이구요.
결국 내가 보낸 일을 순서대로 하게 될텐데, 이는 메인쓰레드에서 그냥 혼자 일을 해결하는 것과 소모되는 시간이 같을거에요.
그렇기 때문에 사실상 이 경우는 잘 사용하지 않고, 저는 공부할 때 케이스를 나누긴 했으니 '아~ 사실상 메인쓰레드에서 몽땅 일을 하는 거랑 비슷하구나~' 로 이해했습니다.
그럼 GCD는 만능?
만능은 아닙니다.
GCD를 이용하게 되면 발견되는 현상이 있는데요 바로 Thread Explosion입니다. 말 그대로 쓰레드 폭.발.
쓰레드가 과도하게 많아지는 현상이에요.
쓰레드가 많아지면 쓰레드 수만큼 Context Switching이 일어난다고 해요.. 쓰레드가 100개면? 100번의 Context Switching이 일어나는데요.. 이는 상당한 오버헤드를 발생시키고, 이는 곧 앱 퍼포먼스를 저해하게 됩니다.
이러한 현상을 막아주는 안전한 코드 작성을 위해 새로 나온 친구가 있습니다..!
그것은 바로 Swift Concurrency..!!!
이 친구는 다음 기회에 들고 글 써보겠습니다.
.
.
.
.
오늘은 여기까지~
'Swift' 카테고리의 다른 글
[iOS] About Hot & Cold Observable (1) | 2024.09.03 |
---|---|
[iOS] About Calendar (0) | 2024.08.28 |
[iOS] About Pagination (0) | 2024.08.21 |
[iOS] About Subscribe, Bind, Driver + @ (0) | 2024.08.17 |
[iOS] About RxSwift (0) | 2024.08.11 |