[iOS] 차근차근 시작하는 GCD — 4
Previously on GCD…
우리는 저번시간에 queue.async { task }
또는 queue.sync { task }
를 통해 task를 queue로 보냈어요!
이제 쌓여 있는 task 들을 다른 스레드로 보내야겠죠?
이때 GCD 혹은 Operation의 선택은 어떻게 될까요?
- 한개의 스레드에 몰아 넣는다
2. 여러개의 스레드에 나눈다
뭐 둘 다 가능은 하겠죠? 이때, 둘 중 어떤 방식을 선택할건지가 바로 queue의 특성에 따라 결정됩니다!
큐의 특성인 Serial(직렬)와 Concurrent(동시)에 대한 이야기 지금 바로 시작합니다.
Serial(직렬)
Serial Queue를 그림으로 봅시다.
자 바로 이해가 가시나요?
(보통 메인 스레드에서) 분산 처리 시킨 작업을 “다른 한개의 스레드에서” 처리하는 큐
가 바로 Serial(직렬) Queue 입니다. 한개의! 스레드! 에서요!
Concurrent(동시)
Concurrent Queue를 그림으로 봅시다.
이것도 바로 이해가 가실까요?!
(보통 메인 스레드에서) 분산 처리 시킨 작업을 “다른 여러개의 스레드에서” 처리하는 큐
가 바로 Concurrent(동시) Queue 입니다. 여러개의! 스레드! 에서요! 몇개의 스레드로 분산할지는 시스템이 알아서 결정합니다.
어떤 큐를 사용할 것인가
위의 설명을 쭉 보고나면 이런 의문점이 들 수 있어요.
흠.. 그럼 언제 Serial 큐를 쓰고 언제 Concurrent 큐를 쓴담? 분산 처리 하는거면.. Concurrent가 좋아보이긴 하는데!
어떤 큐를 사용할 것인지에 대한 핵심 포인트는 바로 작업 순서의 중요도에 있습니다.
Serial 큐에 담긴 작업들은 오직 하나의 스레드에만 분배됩니다. 모든 작업들이 그 전 작업이 끝나길 기다렸다가 하나씩 실행 되기 때문에 task의 시작과 종료에 대한 순서 예측이 가능합니다.
반면 Concurrent 큐에 담긴 작업들은 여러개의 스레드로 분배됩니다. 선입선출이라는 Queue의 특성상 작업들이 순서대로 분배되어 실행되긴 하겠지만, 그것들이 끝나는 순서는 알 수 없습니다.
예를 들어 각 cell에서 이미지를 로드해야한다고 할때, 어떤 데이터가 먼저 들어와야 할지 순서는 중요하지 않습니다. 그냥 빠르면 좋은거예요! 이런 상황에서는 Concurrent Queue 를 사용합니다.
하지만 반대로, 순서가 중요한 작업들을 처리해야 한다면 늦게 들어온 것이 먼저 끝나는 상황 등의 방지를 위해 Serial Queue를 써야겠죠?
마치며
GCD로 구글링 좀 해보신 분들이라면 아시겠지만 꼭 빠지지 않고 나오는 네가지 개념이
- sync(동기)
- async(비동기)
- serial(직렬)
- concurrent(동시)
이거잖아요?
그리고 async / sync
와 concurrent / serial
는 별개의 개념이기 때문에 연관 지어 생각하지 말고.. 헷갈리지도 말라고도 써있쥬..!
하지만 뭔가 serial — sync
, async — concurrent
이렇게 연관 있어 보이는걸..? 흑흑..하며 그저 하염없이 눈물만 흘려왔읍니다..
하지만 이제는 대답할 수 있어요!
비동기(Async)란 말과 동시(Concurrent)란 말이 같은 말인가?
흥 뭔 소리야! 아예 별개의 개념이라고!
async vs sync
작업을 보내는 시점에서 기다릴지 말지에 대해 다루는 것
concurrent vs serial
Queue(대기열)로 보내진 작업들을 여러개의 스레드로 보낼 것인지 한개의 스레드로 보낼 것인지에 대해 다루는 것
그럼 네가지 조합이 나올 수 있겠지!
SerialQueue.sync
: 메인 스레드의 작업 흐름이 queue에 넘긴 태스크가 끝날때까지 멈춰있고(sync
), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 같은 스레드에 보내지기 때문에 해당 작업들이 모두 끝나야 실행 (Serial Queue
)
ConcurrentQueue.sync
: 메인 스레드의 작업 흐름이 queue에 넘긴 태스크가 끝날때까지 멈춰있고(sync
), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 다른 스레드에 보내질 수 있기 때문에 해당 작업들이 모두 끝나지 않아도 실행 (Concurrent Queue
)
SerialQueue.async
: 메인 스레드의 작업 흐름이 태스크를 queue에 넘기자마자 반환되고 (async
), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 같은 스레드에 보내지기 때문에 해당 작업들이 모두 끝나야 실행 (Serial Queue
)
ConcurrentQueue.async
: 메인 스레드의 작업 흐름이 태스크를 queue에 넘기자마자 반환되고 (async
), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 다른 스레드에 보내질 수 있기 때문에 해당 작업들이 모두 끝나지 않아도 실행 (Concurrent Queue
)
후.. 이 인프런 강의 저 같은 GCD 바보도 이해할 수 있게 설명도 깔끔하고 너무 좋군요ㅠ 최고의 강의 추천합니다! 👍🏻