iOS Concurrency: GCD - 1. 기본개념

J.Noma·2021년 12월 18일
0

iOS : 동시성

목록 보기
1/3

내용전반: iOS개발자 앨런
내용전반: naljin님 블로그


📌 학습목표

  • iOS에서 동시성 구현을 위해 주로 사용되는 GCD의 컨셉에 대해 이해합니다
  • GCD와 Operation의 차이에 대해 간략히 짚어 봅니다
  • GCD에서 sync와 async의 차이를 이해합니다
  • GCD에서 Serial과 Concurrency의 차이를 이해합니다

🐶 Concurrency Programming in iOS

컴퓨터는 성능 개선을 위해 멀티코어/멀티프로세스/멀티스레드 등 다양한 동시처리 기법들을 사용하게 됩니다. 언어와 프로그램을 실행하는 플랫폼마다 이 기법들을 어떻게 프로그래밍할지와 구체적인 메커니즘이 상이합니다

iOS를 비롯한 Apple의 플랫폼에서는 프로그래머가 (어떤 상황에 몇 개의 스레드를 할당한다던지 하는) 메커니즘을 구체적으로 정의하지 않고 GCD(Grand Central Dispatch)라는 API를 사용하여 동시성을 구현하게 됩니다. (그 외에, GCD의 확장판인 Operation과 Swift5.5의 async/await가 있습니다)

GCD를 사용하면 대상이 되는 작업(Task)를 대기행렬(큐)에 보내기만 하면 OS가 알아서 스레드를 생성/관리/해제하며 분산처리합니다


🐰 GCD vs Operation

대기행렬(큐)의 종류에는 'GCD / Operation' 2가지가 있으며 프로젝트의 효율성, 사례 적합성을 따져 선택하게 됩니다. (Swift5.5의 await/async는 이번 포스팅에서 다루지 않습니다)

1. GCD

  • DispatchQueue
  • 클로저/메서드로 묶을 수 있는 간단한 작업
  • GCD에서 Task는 클로저 단위로 등록합니다

2. Operation

  • OperationQueue
  • GCD에 비해 상대적으로 복잡한 작업
  • GCD에 기반하여 여러 기능을 추가한 것 (취소/순서지정/일시정지 등)

🐭 Synchornous(동기) vs Asynchornous(비동기) in GCD

GCD 즉, DispatchQueue에서의 sync/async 개념에 대해 알아봅니다

1. Synchornous(동기)

  • 누가? 원래의 작업이 진행되고 있던 스레드가
  • 무엇을? DispatchQueue로 맡긴 Task가 완료될 때까지
  • 어떻게? 다른 작업을 하지않고 기다립니다

사실 sync는 거의 사용되지 않긴 합니다. 이렇게 기다릴거면 굳이 DispatchQueue로 보낼게 아니라 메인 스레드에서 수행하면 되기 때문입니다. 하지만, sync가 필요한 경우도 분명 존재하며 예시는 나중에 다른 섹션에서 다룹니다

2. Asynchornous(비동기)

  • 누가? 원래의 작업이 진행되고 있던 스레드가
  • 무엇을? DispatchQueue로 맡긴 Task가 완료되는 것을
  • 어떻게? 기다리지 않는다

비동기로 맡긴 Task의 완료시점/결과는 CompeletionHandler 클로저를 함께 동봉함으로써 전달받을 수 있습니다. CompletionHandler를 동봉하는 방법에 대해서는 나중에 다른 섹션에서 다룹니다

❓비동기는 왜 필요할까
오래 걸리는 작업이 원인으로 그 중 대부분은 서버와의 통신(네트워크 작업) 때문입니다. 실제로 iOS의 네트워크 관련 작업들은 내부적으로 비동기적으로 알아서 구현되어 있습니다
(ex. URLSession은 바로 사용하더라도 알아서 다른 스레드에서 비동기적으로 수행합니다)


🦊 Serial(직렬) vs Concurrent(동시) in GCD

GCD를 사용하는 우리는 작업들을 하나의 스레드가 순차적으로(Serial) 수행하게 할지, 여러 스레드가 동시에(Concurrent) 수행하게 할지 선택할 수 있습니다.

이 선택은 우리가 작업을 어떤 특성을 가진 '큐'에 맡기느냐로 결정됩니다. GCD에서 큐는 크게 Serial과 Concurrent. 2가지 종류로 나뉘고 각각으로 맡긴 작업들은 아래와 같은 메커니즘으로 처리됩니다

1. Serial Queue

Serial 큐에 담기는 작업들은 오직 하나의 스레드에 할당됩니다. 따라서 작업들이 순차적으로 처리되는 특징이 있습니다. 순서가 중요한 작업과 공유 자원에 동시에 접근하지 못하도록 Mutual Exclusion을 구현해야 하는 경우(Thread-safe) 등의 경우에 사용됩니다

참고
'하나의 스레드'라는 표현에서 스레드는 하이퍼스레딩을 말하는 물리적 스레드가 아니라, 소프트웨어적인 스레드를 말합니다. 그리고 이 하나의 스레드는 경우에 따라 변경될 수도 있습니다. 중간에 일을 안하고 쉬는 텀이 있으면 해제되었다가 새로운 스레드로 교체될 수 있습니다. 하지만, 이 교체작업은 우리가 인지할 수 없도록 잘 동작하므로 개발자 입장에서는 Serial 큐는 '하나의 스레드에 작업을 할당하는 큐다'라고 생각하는 것이 더 유리합니다.
+ 참고로, 메인 스레드의 경우 App과 Life Cycle을 함께 하므로 교체되지 않습니다

2. Concurrent Queue

Concurrent 큐에 담기는 작업들은 여러 개의 스레드로 할당됩니다. 비록 큐에 쌓이는 것은 순차적이겠으나 이 작업들이 여러 스레드들로 분배되어 동시에 처리되므로 처리순서를 예측할 수 없습니다. 하지만 이런 동시처리는 성능을 뽑아내기 위해 존재하므로, Concurrent 큐의 용도는 각자 독립적이면서 중요도/성격이 유사한 여러 개의 작업(ex. 인스타그램 피드)인 경우 등에 사용됩니다

profile
노션으로 이사갑니다 https://tungsten-run-778.notion.site/Study-Archive-98e51c3793684d428070695d5722d1fe

0개의 댓글