이전 포스팅
조하~
여러분 연말 잘 보내고 계신가요?? 저번 시간엔 가볍게? GCD의 등장배경에 대해 알아보았습니다. GCD는 알고보니 우리를 도와주는 아주 착한 친구였죠!!!
등장배경을 알았으니 드디어 GCD에 대해 제대로 알아보아야겠죠!!! 개인적으로 GCD를 공부하며 가장 헷갈렸던 것이 바로 동기/비동기, 직렬/동시의 개념에 대한 이해와 차이였습니다. 볼 때 마다 새롭고... 헷갈리고... 그랬던거 같아요.
네! 그래서 오늘은 바로 GCD에서 가장 헷갈리고 조금은 어려운 동기/비동기, 직렬(메인)/동시에 대한 개념 그리고 GCD가 뭔지 가볍게 살펴보고자합니다. 그러면 바로 레쓰기릿🔥
GCD 누구냐 넌...
GCD(Grand Central Dispatch)
GCD는 맥 OSX 스노우 레오파드(2009년)에 최초로 공개된 기술로 백그라운드에서 스레드를 관리하며 동시적으로 작업을 실행시키는 저수준 API를 제공하는 C언어로 만들어진 라이브러리입니다. (출처: Wikipedia)
기존에 Thread Programming을 하기 위해서는 동기화 관리, deadklock 관리 등 스레드풀을 직접 개발자가 관리해야하는 번거로움이 있었습니다.
하지만 GCD가 등장한 이후로 개발자가 작업을 큐에만 보내주면 GCD가 알아서 스레드 풀에서 스레드를 가져오고 알아서 분배해줍니다.
즉, GCD란 우리가 큐로 보낸 작업을 적절하게 스레드에게 분배해주는 라이브러리 입니다.
GCD가 나타나기 전과 후를 다음 그림과 같이 표현할 수 있을 것 같습니다.
DispatchQueue
네? DispatchQueue가 GCD 아닌가요? 네 정확히 말하자면 아닙니다!!!
저도 처음에 이 부분이 가장 헷갈렸습니다. GCD를 DispatchQueue라고 하는 글들을 많이 봤었기 때문에... 크게 보면 뭐 GCD를 DispatchQueue라고 말 할수도! 있겠지만 정확히 말하자면 조금 다릅니다.
DispatchQueue는 어떤 큐를 만들지 그리고 작업을 동기처리로 할지 비동기처리로 할지 정하고 만들어진 큐로 보내주는 것까지를 관리해주는 클래스입니다.
그리고 큐로 보낸 것을 GCD가 받아 적절하게 스레드에 분배해주는 겁니다. 참고로 GCD는 애초에 운영체제단에서 돌아가는 백그라운드 시스템이기 때문에 따로 신경쓸 필욘 없습니다. 우리는 단지 DispatchQueue로 어떤 큐로 보낼지!만 고려하면 됩니다.
자 그러면 GCD가 무엇인지 DispatchQueue가 무엇인지 정리가 되셨죠? 그럼 이제 동기/비동기 직렬큐/동시큐에 대해 알아봅시다!!!
🔎 동기(Sync)/비동기(Async)
✅ 비동기(Async)
먼저 비동기(Async)처리에 대해 알아보겠습니다. 다시 🍔슈비버거를 가지고 이야기 해보겠습니다.
슈비버거를 만들기위해선 소고기패티, 새우패티, 토마토소스, 양상추 등등이 필요합니다.
만약 이 작업을 하나씩하나씩 처리하면 어떻게 될까요? 다음과 같이 말이죠.
주문이 들어오면 패티를 굽고 패티 굽는게 끝나면 새우패티를 튀기고 튀기는게 끝나면 양상추를 썰고 썰었으면 빵을 굽고... 이런식으로 하나씩 작업을 하고 끝나고 하고 끝나고 순서대로 처리하면 버거 하나를 만드는데 30분 이상의 시간이 걸릴겁니다.
이런식으로 버거를 만들면 손님이 아무도 그 가게에 안 갈겁니다. 가게가 망하겠죠?ㅠㅠ
그러면 이 작업은 하나 시작하고 끝나고 다음 하나 시작하고 끝나고 하는 것이 아니라 패티를 그릴판에 굽고 굽는동안 새우패티를 튀김기에 넣고 튀겨지는 동안 양상추도 썰고 빵도 굽고 바로바로 다음작업을 진행해 버거가 빠르게 만들어질 수 있도록 해야하는 겁니다.
이렇게 바로바로 작업이 끝나지 않아도 다음 작업을 수행하는 것을 비동기처리 라고 합니다. 그림으로 살펴볼게요.
위에서 이야기한 작업을 다음과 같은 그림으로 표현할 수 있습니다. 여기서 스레드1은 메인스레드입니다.
순서대로 한 번 살펴보겠습니다.
비동기(Async)로 작업을 실행하면 먼저 "패티굽기" 작업을 큐로 보내게됩니다. 그리고 큐에가면 GCD가 알아서 쓰레드에 "패티굽기" 작업을 보내줍니다.
그리고 스레드로 보내고나면 리턴을 바로 해줍니다. 그러면 "패티굽기" 작업이 끝나지도 않았는데 "새우패티 튀기기" 작업을 큐로 보내게되고 또 쓰레드에 분배해줍니다. 그리고 아래 그림과 같이 이러한 흐름이 반복됩니다.
비동기(Async) 처리는 작업을 시작하고 마칠 때 까지 안 기다리고 다음 작업을 받아 또 시작합니다. 작업이 끝나지 않아도 즉시리턴!을 해서 다음작업을 시작한다고 보면됩니다. "비동기는 즉시리턴"을 기억하시면 좋을거 같아요 :)
✅ 동기(Sync)
다음은 동기(Sync)처리에 대해 알아보겠습니다. 이번에도 다시 🍔슈비버거를 가지고 이야기 해보겠습니다.
슈비버거 주문이 들어왔습니다. 그럼 슈비버거를 만들어야겠죠?
먼저 빵을 깔고 빵에 소스를 뿌리고 그 위에 양상추를 올리고 새우패티, 소고기패티 올리고 토마토도 올리고 마무리로 래핑까지 순서대로 만들어야 할 것입니다.
만약 이 순서를 무시한다면 패티위에 빵이 올라가거나 양상추 위에 빵이 올라가는 등 이상한 버거가 만들어질 것입니다.
이와 같이 작업이 끝나야 다음 작업을 수행하는 것을 동기처리라고 합니다. 그림으로 살펴볼게요.
위에서 이야기한 작업을 다음과 같은 그림으로 표현할 수 있습니다. 여기서 스레드1은 메인스레드입니다.
순서대로 살펴보겠습니다.
동기(Sync)로 작업을 실행하면 먼저 "빵 깔기" 작업을 큐로 보내게됩니다. 그리고 큐에가면 GCD가 알아서 스레드에 "빵 깔기" 작업을 보내줍니다.
그리고 스레드로 보내지면 보내진 스레드에서 "빵 깔기" 작업이 끝날 때까지 기다리게되고 끝나고난 후 리턴을 하게됩니다. 그리고 "소스 뿌리기" 작업을 큐로 보냅니다. 이러한 흐름이 아래 그림과 같이 반복됩니다.
동기(Sync) 처리는 작업을 시작하고 마칠 때 까지 기다리고 다음 작업을 받아 또 시작합니다. 작업이 끝나고 리턴!을 해서 다음작업을 시작한다고 보면됩니다. "동기는 작업이 끝나고 리턴"을 기억하시면 좋을거 같아요 :)
🔎 직렬(Serial)/동시(Concurrent)
동기/비동기에 대해 알아봤으니 이제 직렬(Serail)/동시(Concurrent)에 대해 알아보겠습니다. 그 전에 직렬과 동시는 큐의 특성이다! 라는 것을 기억하시고 가면 좋을 것 같습니다.
큐는 뭐였죠? 네 큐(Queue)는 DispatchQueue 클래스로 작업을 보내주는 곳입니다. 위의 그림에서 1번 스레드(메인 스레드)에서 작업을 큐로 보내준 것을 확인하실 수 있을겁니다. 참고로 큐는 FIFO(First in First out) 선입선출의 특성을 가지고 있습니다.
✅ 직렬(Serial)
작업을 직렬큐로 보내면 GCD는 스레드를 하나만 가져오고 그 한 스레드에 작업을 전달해줍니다. 한 스레드에서만 작업이 되는 것이기 때문에 메인스레드가 작업하는 형태랑 같다고 볼 수 있겠습니다.
그림과 같이 "햄버거 만드는 작업"을 직렬큐로 보내고 스레드2로만 작업이 분배되어 처리되어 집니다.
그렇다면 이제 배웠던 개념을 합쳐서 응용해보겠습니다. 참고로 아래 코드에서 설정한 serialQueue는 메인큐와 동일시 생각하셔도 됩니다.
⭐️ 직렬큐 + 동기처리
영상에서 볼 수 있듯 작업이 순서대로 이루어지는 것을 확인할 수 있습니다. 이 흐름을 그림으로 표현하면 다음과 같습니다.
"시작" 작업이 처리되면 작업을 직렬큐로 보내고 하나의 스레드로 분배됩니다.
보내진 작업은 순서대로 처리되어야 하기 때문에 스레드1에 대기블록이 생기고 스레드2에 보내진 작업이 모두 끝나면 마지막으로 "끝" 작업이 스레드1에서 실행됩니다.
때문에 "직렬큐 + 동기처리"는 "하나의 스레드로 보내서 작업하고, 그 작업이 하나씩 순서대로 이루어지는 것"이라고 할 수 있습니다.
⭐️ 직렬큐 + 비동기처리
영상에서 볼 수 있듯 "직렬큐 + 동기처리"와는 달리 "끝" 작업이 빠르게 끝나는 것을 볼 수있습니다. 이 흐름을 그림으로 표현하면 다음과 같습니다.
"시작" 작업이 처리되면 작업을 직렬큐로 보내고 하나의 스레드로 분배됩니다.
보내진 작업은 바로 리턴하게되어 작업들이 모두 스레드2로 가면 "끝"작업이 바로 실행됩니다. "직렬 + 동기처리"와 달리 하나씩 순서대로 이루어지지 않게 되는 것이죠.
영상에서 "빵 깔기" ~ "래핑하기" 까지의 작업은 순서대로 이루어집니다. 왜냐하면 작업들이 하나의 스레드에서 이루어지기 때문입니다. 하나의 스레드에서 작업이 뒤죽박죽으로 실행되면 안 되겠죠???
때문에 "직렬큐 + 비동기처리"는 "하나의 스레드로 보내서 작업하되 보낸 스레드(스레드1)는 모든 작업을 큐로보내면 바로 작업이 끝나고,
보내진 스레드(스레드2)는 작업이 하나씩 순서대로 이루어지는 것"이라고 할 수 있습니다.
✅ 동시(Concurrent)
작업을 동시큐로 보내면 GCD는 스레드를 여러개 가져오고 여러 스레드에 작업을 분배해줍니다. 때문에 여러스레드에서 작업을 할 수 있게 됩니다.
그림과 같이 "햄버거 만드는 작업"을 동시큐(ConcurrentQueue)로 보내고 스레드2, 스레드3, 스레드4, 스레드5로 작업이 분배되어 처리되어 집니다.(스레드 2, 3 ,4, 5는 예시입니다 더 많은 스레드에 보내질 수도 있어요!)
그렇다면 배웠던 개념을 합쳐서 응용해보겠습니다.
⭐️ 동시큐 + 동기처리
영상에서 볼 수 있듯 작업이 순서대로 이루어지는 것을 확인할 수 있습니다. 여러 스레드에서 작업을 하는데도 불구하고 말이죠. 이 흐름을 그림으로 한 번 살펴봅시다.
"시작" 작업이 처리되면 작업들이 하나씩 여러 스레드로 분배되고 순서대로 처리되어야 하기 때문에 스레드1에 대기블록이 생깁니다. 그리고 각각의 스레드에 보내진 작업이 모두 끝나면 마지막으로 "끝" 작업이 스레드1에서 실행됩니다.
스레드의 갯수가 많다고해서 작업이 바로바로 끝나는 것은 절대!!! 아닙니다. 여러 스레드에서 작업을 하더라도 동기(Sync)처리를 하면 여러 스레드에 있는 작업들이 순서대로 이루어져야하기 때문입니다.
"동시큐 + 동기처리"는 "여러 스레드로 보내서 작업하고, 여러 스레드의 작업들이 하나씩 순서대로 이루어지는 것"이라고 할 수 있습니다.
⭐️ 동시큐 + 비동기처리
영상에서 볼 수 있듯 작업이 동시에 이루어지는 것을 확인할 수 있습니다. 여러 스레드에서 작업을 동시에 하는것이죠. 이 흐름을 그림으로 한 번 살펴봅시다.
"시작" 작업이 처리되면 작업들이 하나씩 여러 스레드로 분배되고 분배된 여러 스레드에서 바로바로 실행됩니다.
여러 스레드에서 작업을 비동기(Async)로 처리를 하기 때문에 바로 실행 -> 리턴, 실행 -> 리턴이 반복되어 다음과 같이 작업이 이루어지는 것입니다.
"동시큐 + 비동기처리"는 "여러 스레드로 보내서 작업하고, 여러 스레드의 작업들이 동시에 이루어지는 것"이라고 할 수 있습니다.
후... 그림에 동영상까지 넣으니... 글이 많이 길어졌네요.
하지만 아시다시피 동기/비동기 직렬/동시는 정말 중요한 개념이니 꼭 이해하시고 넘어가시면 좋겠습니다. :)
아 그리고 틀린 부분 있으면 피드백 환영이니 꼭 주시구요. 이해 안되는 부분 있으면 댓글 달아주시면 답해드리겠습니다.
그럼 정리하고 마무리 할게요!!!
📌 정리
- 동기(Sync)는 작업이 하나씩 순서대로 처리되는 것(작업 끝나고 리턴!)
- 비동기(Async)는 작업이 끝나지 않아도 다음 작업을 시작하는 것(작업 안 끝나도 바로 리턴!)
- 직렬(Serial)은 큐의 종류로 직렬큐(Serial Queue)에 보내면 작업이 하나의 스레드에서 이루어진다.
- 동시(Concurrent)는 큐의 종류로 동시큐(Concurrent Queue)에 보내면 작업이 여러 스레드에서 이루어진다.
- 직렬(Serial) + 동기(Sync)는 하나의 스레드에서 작업이 순서대로 이루어지는 것
- 직렬(Serial) + 비동기(Async)는 보낸 스레드, 보내진 스레드 에서 작업이 동시에 이루어지는 것
- 동시(Concurrent) + 동기(Sync)는 여러 스레드에서 작업이 순서대로 이루어지는 것
- 동시(Concurrent) + 비동기(Async)는 여러 스레드에서 작업이 동시에 이루어지는 것
📄 참고
'iOS' 카테고리의 다른 글
[iOS] - UI작업은 왜 메인스레드에서 이루어져야하나 (0) | 2022.12.29 |
---|---|
[iOS] GCD 누구냐 넌 - 1. GCD의 등장배경 (0) | 2022.12.26 |
[iOS] - Realm 마이그레이션 정리 (0) | 2022.10.13 |
[iOS] - Push Notification(feat. Firebase) (0) | 2022.10.11 |
[iOS] Map Kit View 사용하기 - 1 (0) | 2022.08.11 |