맛동산이

Swift) Dispatch Group이란, 사용하는 방법 본문

앱/Swift

Swift) Dispatch Group이란, 사용하는 방법

진ddang 2023. 8. 28. 15:13

 

Concurrent라는 뜻

iOS에서는 time Slicing을 하고 있다. (당연한 이야기)

따라서 single Thread라면, context switching을 통해서 병렬적 작업을

muti Thread라면 parallelism하게 동작한다.

DispatchQueue

DispatchQueue는 GCD의 쓰레드의 관리를 위한 객체가 존재함

해당 객체의 존재는 serial 과 concurrent queue두개가 존재

  • serial : task의 시간을 보장해주며, 순차적으로 진행
  • concurrent : 동시에 여러 task를 수행할수 있음

기본적으로 serial임.

let queue = DispatchQueue(label: "start") queue.async {     for i in 0...5 {         sleep(1)         print("\(i)")     } }  queue.async {     for i in 10...15 {         sleep(1)         print(i)     } } 

Untitled.png

결과

concurrent queue의 실행시

let queue = DispatchQueue(label: "start", attributes: .concurrent) queue.async {     for i in 0...5 {         sleep(1)         print("\(i)")     } }  queue.async {     for i in 10...15 {         sleep(1)         print(i)     } } 

Untitled.png

결과

async, sync

DispatchQueue에서의 concurrent는 앞의 task의 결과를 기다리지 않고, 바로 실행됨을 의미함.

이때 serial라면, 앞의 task가 끝나기를 기다리며, 이때 DispatchQueue에서는 thread를 block하게됨.

  • thread block이란, 해당 스레드가 다른 작업을 수행을 못함을 의미함.

DispatchQueue의 종류

  1. main : serial queue
  2. global : concurrent queue이며 4개의 qos를 가짐
  3. custom : whether serial or concurrent queue.

DispatchGroup

Untitled.pngUntitled.png

DispatchGroup은 Grouping을 통해서 여러 dispatchQueue의 동작들이 끝났을때 어떠한 행동을 할수있도록 해주는 클래스이다.

비동기 Task는 다음과 같이 다양하게 존재하는데

  • UI( interface )
  • Data Transform
  • Database
  • Networking

이러한 동작들이 하나의 그룹으로 묶여서, 해당 동작이 다 끝났을때 어떠한 noti를 주고 싶다면 dispatchGroup을 사용하면 된다.

💡 여러개의 DispatchQueue들의 일이 끝남을 알기 위할때 DispatchGroup으로 묶어서 사용하면된다.

DispatchGroup사용방법

  • notify : DispatchGroup에 task가 0이 되면 실행되는 메소드
  • leave : group task -1
  • enter : group task +1
let queue1 = DispatchQueue(label: "queue1", attributes: .concurrent)         let queue2 = DispatchQueue(label: "queue2", attributes: .concurrent)          let group = DispatchGroup()         queue1.async(group: group) {             for i in 0...5 {                 print(i)             }         }         queue2.async(group: group) {             for i in 100...105 {                 print(i)             }         }          let queueForGroup = DispatchQueue(label: "queue3", attributes: .concurrent)         group.notify(queue: queueForGroup) { // group이 끝난 후 후행 클로저를 실행할 queue삽입             print("끝")         } 

Qos???????

DispatchQueue를 쓰다보면, qos라는개념이 나오는데 이게 정확히 어떨때 쓰게되는지에 대해서 궁금했었다.

하지만 DispatchGroup을 쓰면서 완벽하게 이해가 되었다!!!!!

DispatchGroup은 Group내부의 여러개의 dispatchQueue를 가지게 되는데,

다음과 같은 task들이 있다면 어떻게 될것인가 상상해보자

Untitled.png

우선적으로 우리의 순서는 네트워킹을 통해서 데이터베이스의 값을 받아오고, 데이터를 변경해준다음 ui를 변경해주는 일련의 순서를 거쳐야 한다.

하지만, dispatchQueue들은 서로다른 스레드에서 동작하게 되며, 이는 동시성이기 때문에 서로 순서 상관없이 동작할 가능성이 크다.

이때 Qos를 주는것이다!!

Qos 종류

// 애니메이션과 같은 UI 즉시 업데이트가 필요하며, 멈춘것처럼 보이지 않는 작업들 (유저의 반응) DispatchQueue.global(qos: .userInteactive)  // 저장된 문서를 열거나, 유저가 무언가 클릭했을 때 작업을 수행하고 즉각 보여주어야 하는 것 (몇초) DispatchQueue.global(qos: .userInitiated)  // 기본 서비스 (일반적인 경우 - userInitiated와 utility의 중간정도의 우선순위) DispatchQueue.global(qos: .default)  // 보통 프로그레스바를 같이 사용하는 작업 DispatchQueue.global(qos: .utility)  // 유저에게 표시되지 않는 동기화, 안정화, 백업과 같은 일 DispatchQueue.global(qos: .background) 

참고자료

bookmark

bookmark

반응형