본문 바로가기

iOS/iOS

iOS) GCD (Grand Central Dispatch)

 

 

안녕하세요 :) 소들입니다..

오늘은 iOS의 이 쓰레드란 놈에 대해 마무리를 지어볼까 해요..

아마 이번에 GCD좀 다루면 대강 끝나지 않을까 싶네요 :)

 

먼저 iOS의

Main Thread / Global Thread 에 대해서 이해를 하고,

그 뒤에 NSOperation과 GCD를 다뤄볼까 합니다 :)

 

Sync / Async, Serial / Concurrent에 대한 기본지식이 있다는 전제 하에 진행하니

혹시 모른다면 이 포스팅을 꼭 보고 와주세염~~~~~~

 

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. Main Thread / Global Thread

 

음..... 개발을 하다보면

정말 많이보게 되는 그런 녀석들임 이것들에 대해 먼저 짚고 넘어가겠음 👀

 

 

 

1-1. Main Thread

 

iOS에서 Main Thread는 오직 한 개만 존재함!

우리가 평소에 아무렇지 않게 작성하는 코드들이 바로 이 Main Thread에서 동작하는 것인데,

이 작성된 코드가 Cocoa에서 실행될 때, Main Thread에서 호출하기 때문임!!

 

또 Main Thread의 중요한 것 중 하나는,

이 Main Thread는 Interface Thread라고도 불리는데, 

그 이유는 UI와 관련된 작업은 모두 이 Main Thread에 붙기 때문에,

UI와 관련된 작업은 반드시 Main Thread에서 작성해야 함!!

 

만약 Main Thread가 아닌 곳에서 UI 관련 작업을 실행하려고 하면

 

 

 

이런 식으로 RunTime 중에 보라색 오류가 남 👀

근데 이 Main Thread에서 시간이 걸리는 작업을 실행하게 되면,

그동안 어플 화면이 정지된 것처럼 멈춰있음

 

왜냐면 좀이따 나올거지만, Main ThreadMain Queue에서 실행되는데,

Main Queue가 Serial Queue라서, 한번에 한 개의 Task밖에 실행하지 못함

 

따라서, UI를 실행하는 데에 영향을 줄만한 코드들Main Thread에서 실행하면 안 되고,

다음에 나오는 Global Thread로 실행시켜 줘야 함 :)

 

 

 

1-2. Global Thread (Background Thread)

 

편의상 Background Thread라고 부르겠음!

iOS에서의 Framework들은 모두 Background에서 구동이 됨

몸체는 Background에 있지만, 가끔 필요할 때 Main Thread에게 손(Delegate)을 뻗는 구조임!

 

무슨 말이냐면

예를 들어, 우리가 어플에서 음악을 재생하려고 하면 음악 재생에 필요한 Framework를 쓸 것이잖음?

이때 음악 재생에 필요한 Framework 작업들은 모두 Background에서 실행되고,

필요에 따라 음악 재생 성공했다! 같은 것을 알려줄 때 Delegate, Completion Handler 등을 통해

Main Thread에게 알려 통제할 수 있는 것임

 

만약 iOS Framework 작업이 모두 Main Thread에서 작동한다면,

앱의 화면은 계~~~~~속 멈춰있을 것임!! 

 

근데, 자동으로 Background에서 실행되는 것 외에도

코드 실행이 오래 걸리는 작업은 직접 Background Thread로 실행시켜주어야 함

 

 

자, 이제 Thread 종류에 대해 알았으니

Queue 종류에 대해 알아보자 :)

 

 

 

 

2. NSOperation / GCD

 

앞서, Thread의 종류와 사용 이유?에 대해 알아봤다면,

iOS에선 Multi Threading 할 때 어떤 방식으로 하는지 알아보겠음!

 

먼저 애플은 쉽고편한 Multi Threading을 위하여 2가지 API를 제공하는데

 

NSOperation

GCD

 

이 외에 NSThread도 있지만 이 두가지에 대해서만 다루겠음!!

(그중에서 오늘 내용은 GCD이기에 NSOperation은 간단히 ㅎㅎ)

 

 

 

2-1. NSOperation

 

Objective-C언어 기반의 고수준 API

 

NSOperation은 내부적으로는 C로 구현된 GCD를 고수준 언어로 Wrapping 한 것이고,

따라서  GCD보다 다소 무겁고 약간의 오버헤드를 발생시킴!!

 

하지만 고수준 API인 만큼,

GCD엔 없는 기능들을 사용할 수 있다는 장점을 가지고 있음

대충 어떤 기능들이냐면,

 

작업 취소, KVO(나중에 포스팅 할 예정), 작업 재사용 등등

 

GCD에서 하려면 귀찮은 작업들을 제공해서

사용하기 편하다는 장점이 있다 함 :)

 

NSOperation 동작 방식은 작업 단위인

NSOperation을 NSOperationQueue에  추가하여 실행시키는 방법인데,

이때 NSOperation Queue는 Concurrent Queue로 동작함

 

근데 실제 많이 사용하는 건 NSOperation 보다 GCD이니,

NSOperation 사용법은 나중에 따로 포스팅 하겠음 :)

 

 

 

2-2. GCD (Grand Central Dispatch)

 

 C언어 기반의 저수준 API

 

대망의 GCD!!! 드디어 나왔다💩

GCD는 C언어 기반이기 때문에 NSOperation보다 가볍고 성능면에서 좋다!

또한 Block(Closure)로 구현되어 있어 코드 가독성면에서 좋고 간단하게 사용가능 하지만,

작업 취소, KVO, 재사용 등등은 직접 만들어줘야 한다는 귀찮음이 있음😱

 

쨌든 GCD의 정의는 이렇고,

이 GCD는 Dispatch Queue라는 것을 사용해서 Multi Threading을 지원함!

먼저, Dispatch Queue에 대해 알아보자 :)

 

  DIspatch Queue  

 

NSOperation에서 NSOperationQueue를 이용해 작업을 관리 했다면,

GCD에선 이 Dispatch Queue라는 것을 이용해 작업을 관리함!

DIspatch Queue는 2가지 Type이 존재하는데,

 

 

① Serial Queue 

Task(작업)들을 순차적으로 처리하며,

한 번에 한 개의 Task 밖에 처리하지 못함

 

 

 

Concurrent Queue 

 

동시에 여러 개의 Task들을 처리함

Serial / Concurrent에 대한 것은 이전 포스팅에서 다뤘으니 가볍게 넘어갈게여 :)

 

.

.

 

또한 Dispatch Queue는 App이 실행함과 동시에 구조적으로 2가지 Queue가 자동생성되는데,

가장 처음에 언급했던 Main / Global Thread와 관련된내용임!!!

 

 

① Main Queue (Serial Queue) 

 

Main Thread에서 사용되는 QueueSerial Queue이고,

당연히 UI 관련 작업은 이곳에서 처리되어야 함!

 

Main Queue에 작업을 추가하고 싶다면, 다음과 같이 해주면 됨

 

 

DispatchQueue.main.async {
    //원하는 작업
}

 

 

DispatchQueue 중 main queue에 async로 추가하겠다! 이런 식으로 등록함

참고로, Main Queue에는 절대 절대 Sync Task를 추가할 수 없음

 

 

이유는 찾아보니까 Main Thread가 Thread-Safe하지 않아서라는데,

난 아직 이해가 안가서 ;ㅁ; 이해가 가면 나중에 추가 하겠음

 

근데 쨌든, main.sync는 절대절대 사용하면 안됨!!!!!!!!!!!!

컴파일 시에 문제 없는데염?? 하겠지만, 런타임 에러로 떨어지니까 Async만 사용하셈 

 

 

 

② Global Queue (Concurrent Queue) 

 

Global Queue는 편의상 사용할 수 있게 만들어 놓은 Concurrent Queue이고,

정의에서 보다 싶이 Qos라는 것을 지원함

Qos가 뭐냐면, Priority(우선 순위)인데, 이 우선 순위를 우리가 직접 명시해줄 수 있음

 

 

userInteractive 중요도가 높고 즉각적인 반응이 요구되는 작업(UI업데이트, 이벤트핸들링 등)일 때 사용
Main Thread에서 실행되는 Qos
즉각적으로 실행
userInitiated userInteractive까진 아니더라도 유저가 빠른 결과를 기대할 때 사용
저장된 파일을 열거나 할 때 사용
몇 초 이하나 거의 즉각적
default 작업을 분리하지 않을 때 사용되는 Qos로 기본값임  
utility 즉각적인 결과가 필요하지 않을 때
프로그레스 바가 등장하는 작업에 어울림
(네트워크, 다운로드, 계산, 데이터를 가져오기 등을 처리 등)
몇 초 ~ 몇 분
background 급히 필요하지 않은 작업일 때
사용자에겐 보이지 않는 처리 (ex: 백업)
background로 줄 경우 iPhone 저전력 모드에선 실행되지 않는다
몇 분 ~ 몇 시간
unspecified Qos 정보가 없음을 나타냄
시스템에게 Qos를 추론하라는 신호를 줌
 

 

Qos를 잘 활용하면 에너지 효율성이 좋아진다고 함 :)

Global Queue에 작업을 추가하고 싶다면, 다음과 같이 해주면 됨

 

 

DispatchQueue.global().sync {
    //원하는 작업
}
DispatchQueue.global().async {
    //원하는 작업
}

 

sync, async를 지정해서 위와 같이 호출해주면 되고,

Qos를 딱히 지정하지 않으면 .Default로 지정됨!!!!

 

만약, Qos를 지정하고 싶다면

 

 

DispatchQueue.global(qos: .userInteractive).sync {
    //원하는 작업
}

 

 

이런 식으로 직접 지정해주면 됨:)

 

이렇게 자동 생성되는 Queue 외에도

내가 직접 Queue를 만들고 싶다!!!!!111 하면  만들 수 있음

 

 

 

+ Private Queue (사용자 지정 큐) 

다음과 같이 만들면 됨 👀

 

let myQueue = DispatchQueue.init(label: "myQueue", qos: .background attributes: .concurrent)
myQueue.async {
    //원하는 작업
}
 

 

쨘-

 

 

 

 

.

.

.

흠.........

이외에도 Dispatch Semaphore나 Lock 등등에 대해

더 다루고 싶은데 그건 따로 포스팅 하겠습니다 🌝

피드백, 잘못된 내용 환영

 

 



Calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
최근 댓글
Visits
Today
Yesterday