본문 바로가기
iOS/Combine

[iOS/Combine] 스레드 작업처리 방식과 큐의 작업 분산방식(Sync vs Async / serial vs Concurrent)

by iosdevlime 2023. 5. 8.

앞선 포스팅에서 미처 다루지 못한 내용부터 시작해볼까요?

DispatchQueue 란 키워드를 활용해, 큐(Queue)는 스레드에 작업을 분산시키게 됩니다.

 

 

그렇다면,

 

① 큐(Queue)가 작업을 스레드에 분산시키는 방식

각각의 스레드(Thread)가 작업을 처리하는 방식 에 대해

 

코드 예시를 통해 살펴보면서,

궁극적으로 동기/비동기 프로그래밍에 대한 내용도 함께 알아보도록 하겠습니다.

 

 

 

[참고링크]

- 동시성 프로그래밍, 스레드와 큐 
(https://lena-chamna.netlify.app/post/concurrency_programming_thread_and_queue/)

 

 


 

 

 

GCD(Grand Central Dispatch)와 큐(Queue)의 종류

개발자는 큐(Queue)를 만들며, GCD는 스레드 생성 및 스케쥴링을 담당

 

일련의 작업 흐름 - 스레드(S/W) 부터 다시 짚고 넘어가 볼까요?

 

스레드(Thread)는,

단일한 프로세스 - 단일한 작업(Task)에서 나아가, 

동시에 작업을 수행하는 하나의 흐름(Flow 혹은 Context)입니다.

 

즉, 스레드라는 병렬적인 작업흐름을 통해

프로세스의 한계(CPU 오버헤드)를 극복하는

동시성 프로그래밍(Concurrency Programming)의 개념이 등장하게 됩니다. 

 

이와 같은 동시성 프로그래밍을 실행하기 위해

개발자는 큐(Queue)라는 매개체를 생성하게 됩니다.

 

 

그런데, 이러한 큐(Queue)는 어떻게 생성해야 하는거죠? 

 

 

 

GCD(Grand Central Dispatch)

  • GCD란, 스레드 생성과 스케쥴링과 관련된 일을 모두 담당하는 API입니다.
    • 개발자는 DispatchQueue 명령어를 통해 동기 혹은 비동기를 설정합니다.
    • 이후, GCD는 시스템 레벨에서 적절하게 스레드에 작업을 분배합니다.
  • GCD란 Queue API를 활용하기 위해, DispatchQueue란 키워드를 활용합니다.
    • 앞선 포스팅에서 다룬 DispatchQueue가 바로 GCD 활용 방식입니다.

 

 

큐(Queue)의 작업 분산방식

  • 큐(Queue)는 크게 3가지 종류를 가지고 있으며, 이에 따라 상이한 특징을 보입니다.
    • Main Queue : 단일한 메인 스레드이며, Serial 특성을 가집니다.
      (Serial : 직렬형태, 큐가 받아들인 작업을 하나의 스레드에서 처리)
    • Global Queue : 공유되는 다수의 스레드이며, Concurrent 특성을 가집니다.
      (Concurrent : 병렬형태, 큐가 받아들인 작업을 여러개의 스레드로 나눠서 처리)
    • Custom Queue: Serial 혹은 Concurrent Queue 특징의 큐를 사용자가 생성합니다.

메인큐(Main Queue)와 글로벌 큐(Global Queue)의 스레드 분산 방식
메인큐(Main Queue)와 글로벌 큐(Global Queue)의 스레드 분산 방식

 

  • 즉, DispatchQueue 키워드와 함께 활용되는 큐는 작업 분산방식에 따라 작성합니다.
    • DispatchQueue.main (메인큐) : 순서가 중요한 작업을 처리할 때 활용
    • DispatchQueue.global (글로벌 큐) : 독립적이지만 유사한 여러개의 작업을 처리할때 활용
// 메인 큐 - 하나의 메인 스레드에서 작업하도록 하는 Serial(직렬) 방식의 큐
DispatchQueue.main.async {
    // 작업A
} 
// 작업A를 직렬 방식의 (메인)스레드로 처리할거야


// 글로벌 큐 - async(비동기)
DispatchQueue.global().async {
    // 작업B
}
// 작업B를 병렬 방식으로 다양한 스레드에서 처리하도록 할거야

 


 

 

동기(Sync)와 비동기(Async) : 스레드 작업방식

스레드에서의 작업 수행을 위한 요청과 완료에 따른 응답의 형태에 따른 분류

 

GCD(Grand Central Disaptch)를 통한 스레드 생성 및 스케쥴링을 위하여

개발자는 DispatchQueue란 키워드를 통해 큐(Queue)를 생성한다고 살펴보았습니다!

 

조금 헷갈릴 수 있는 부분이니 한번 더 짚고 넘어가도록 합시다.

큐는, 작업 분산 방식에 따라 크게 아래와 같이 3가지로 구분됩니다.

  • 메인 큐(Main Queue) - Serial(직렬) : 단일한 메인 스레드에서 작업(스케쥴링)을 실시
  • 글로벌 큐(Global Queue) - Concurrent(병렬) : 다수의 스레드로 나눠서 작업(스케쥴링)을 실시
  • 커스텀 큐(Custom Queue) : 사용자가 직접 설정하는 큐 (작업 분산 방식 설정)

 

그렇다면,

작업을 분산하는 시점에서 할당받는 스레드는 어떤 방식으로 작업을 요청 받고

요청에 따라 어떤 형태로 응답을 실시할까요?

 

여기서, 등장하는 개념이 바로

동기(Sync), 그리고 비동기(Async)입니다.

 

 

 

스레드 작업방식, 동기(Sync)와 비동기(Async)

  • 큐(Queue)는 작업 분산 방식 이외, 작업을 할당한 '스레드의 작업 방식'도 결정합니다.
    • 작업을 할당받는 스레드의 작업 특성을 정의하는 정의하는 과정입니다.
    • GCD API를 사용하기 위해 작성하는 클로저 구문의 맨 마지막에 선언됩니다.
// DispatchQueue

DispatchQueue.(main 혹은 Global).(sync 혹은 Async) {
	// 작업
}



  • 동기(Sync) 방식이란, 사전적 의미로 '동시에 발생하는' 이란 뜻을 지닙니다.
    • 여기서 동시란, '작업'이 동시에 발생된다는 것이 아닌, 요청과 응답이 동시 발생한다는 의미입니다.
    • 즉, 큐(Queue)에서 작업을 스레드에 요청한 후, 응답이 동시에 발생해야 하므로
      해당 작업이 끝나기 전 까지 다른 작업을 진행할 수 없습니다!

Sync(동기화) 방식 예시 (요청-응답을 동시에)
Sync(동기화) 방식 예시 (요청-응답을 동시에)

 

  • 반대로, 비동기(Sync) 방식이란 응답이 발생하기 전에 다음 요청(작업)을 진행하는 방식입니다. 
    • 결과적으로, 여러가지 작업을 '동시'에 실행하는, 비 동기 방식으로 처리하게 됩니다.
    • 가장 오래 작업이 걸리는 'Figma'가 끝나는 시간이 전체 작업시간이 됩니다.

Async(비동기화) 방식 예시 (응답을 기다리지 않고, 다음 작업을 요청)
Async(비동기화) 방식 예시 (응답을 기다리지 않고, 다음 작업을 요청)

 

 


스레드 작업처리 방식,

그리고 Sync와 Async 방식에 대한 개념을 살펴보았습니다.

 

아직 못다룬 기초 개념은 다음 포스팅에서 다뤄보도록 하겠습니다.

 

댓글