IOS

[IOS / Swift] DispatchQueue.main

hyukji 2022. 12. 14. 02:06

URLSession을 사용하여 데이터를 받아와 ui에 편집할 때 DispatchQueue.main.async를 사용한 코드가 있어 검색을 하며 이해한 내용을 코드에 적고자 한다.

 

 

 

쓰레드(thread)

쓰레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미한다. 쉽게 말해 앱을 수행하는 일꾼(?)이다. 모든 앱은 메인쓰레드를 가지고 있다. 우리가 흔히 사용하는 UIkit의 클래스들은 이 메인 쓰레드에서만 수행된다. 하지만 프로그램의 환경에 따라 쓰레드는 둘 이상의 쓰레드를 사용하기도 한다(멀티쓰레드). 대표적인 예로 앞서 언급한 URLSession의 request, response와 관련된 작업들이다. 쓰레드가 여러개 일때 어떤 작업을 활용할때 메인쓰레드만 사용한다면 다른 쓰레드들은 그저 놀기만 하고 있기 때문에 앱이 굉장히 비효율적으로 돌아갈 것이다. 이때 작업들을 적절한 쓰레드에 배치시키는 것이 GCD이다.

 

 

 

GCD

GCD는  Grand Central Dispatch의 약자로 Dispatch라고 불린다. Dispatch는 앞서 말한 바와 같이 쓰레드들에 작업들을 적절하게 배치해 효율적으로 작업을 수행하도록 한다. 이때 사용되는 것이 Dispatch Queue로 작업들을 전달해 순차적, 동시에 동작을 수행하도록 관리한다. 이때 동기(sync) 혹은 비동기(async)를 설정하게 된다.

 

맨 처음에 말한 URLSession 비동기로 수행하도록 내부적으로 설정되어 있다. 또한 별도의 쓰레드에서 작동하고 있다. UI 업데이트 하는 tableView.reload()같은 코드는 메인 큐에서 작업해야 하는 이미 백그라운드에서 수행되고 있기때문에 메인 쓰레드로 옮겨주기 위해 DispatchQueue.main 매서드를 사용하였다. 

 

 


 

동기 vs 비동기

위 함수 DispatchQueue.main.async 는 메인 쓰레드를 비동기로 실행함을 의미한다. 물론 DispatchQueue.main.sync도 존재한다. 이는 동기로 실행함을 의미한다. 여기서 동기란 코드를 쓰여진 순서대로 차례대로 진행하는 것을 나타낸다. 다시 말해 해당 줄의 코드가 완료되어야 다음 줄로 넘어간다. 비동기는 그렇지 않다. 현재 코드가 완료되지 않앗어도 다음 코드를 실행하기도 한다. 물론 동기가 코드의 로직을 구성하기엔 훨씬 간단하겠지만, 실행 측면에서 본다면 윗 줄이 끝날 때까지 기다리는 동기보다는 비동기가 더 효율적일 때가 많을 것이다.

 

 

 

 

DispatchQueue.main.async

ios에서 ui관련 작업은 메인 쓰레드를 통해 이루어 지며 백그라운드와 같은 무거운 작업들은 다른 쓰레드를 통해 실행된다. 따라서 해당 함수를 ui작업을 메인 쓰레드에서 돌리기 위해 주로 불려진다. 예를 들어 URLSession을 통해 데이터를 받아오는 작업을 생각해보자. 이 작업은 메인쓰레드가 아닌 다른 쓰레드로 진행될 것이다. 그러나 이 과정중에 UI작업이 필요하다면? 메인 쓰레드의 작업을 필요로 한다면 그때 사용되는 것이 DispatchQueue.main.async이다. 해당 함수를 사용하면 필요 상황에 맞추어 메인 쓰레드를 사용할 수 있다.

 

DispatchQueue.main.sync

해당 함수를 사용해 Task를 전달하면 데드락에 걸리게 된다. 즉 앱이 먹통이 된다ㅎ 이미 완료되지 않은 Task가 있는 데 sync으로 데이터를 넣어주었기 때문이다. 메인 쓰레드에서는 sync를 이용한 동기실행을 호출하지 않는 것이 좋다.