본문 바로가기

Android/Tech

Coroutine Dispatcher 란 무엇인가?

Unsplash, Marcin Jozwiak.

 

안드로이드 개발을 꽤 오래 하셨던 분들, 또는 지방에서 일하고 계신 분들은 자바로 안드로이드 개발을 해보셨을겁니다.

저 또한 그랬습니다. 처음 개발을 배울 때부터 자바로 배워서, 코틀린같은 고급 언어는 굉장히 낯설었습니다.

코틀린의 코루틴이 그랬습니다. AsyncTask 나 Thread 를 사용해서 외부와 통신해왔던 저로서는 받아들이기 여간 어려운 것이 아니었습니다.

 

코틀린으로의 전환 이후 가장 처음 마주한 것이 코루틴이었습니다.

코루틴은 다음과 같이 실행됩니다.

 

CoroutineScope(Dispatchers.IO).launch {
	// do something
}

 

CoroutineScope 는 코루틴을 실행시키기 위해서 꼭 필요하다는 것은 쉽게 알 수 있습니다.

그렇다면 Dispatcher 는 뭘까요? 


 

 

Dispatcher 는 운행 관리원 또는 비상 차량 배치 담당자를 의미합니다. 이게 뜬금없이 뭔 소리인가 싶겠지만, Dispatcher 의 역할을 알게 되면 꽤나 어울리는 네이밍이라는 생각도 듭니다.

 

물류 관련 기업의 배차 담당자는 국내(또는 국외)의 수많은 장소에 다양한 경로를 통해 물건을 배달할 차량을 배차하여야합니다. 수많은 차량을 배차하면서도 그와 동시에 효율적으로 운용될 수 있도록 신경써야 합니다.

CoroutineDispatcher 는 말 그대로 수많은 Coroutine 이 효율적으로 각자의 작업을 수행할 수 있도록 신경써주는 오브젝트임을 알 수 있습니다. 

 

각 Dispatcher 객체는 해당 객체가 접근할 수 있는 스레드 풀에 각 작업을 할당하는 역할을 수행합니다. 스레드 풀 내의 스레드중 유휴 스레드가 있다면, 그 스레드에게 입력된 코루틴을 전달, 실행하도록 명령합니다. 간단합니다.


Dispatcher 를 자유롭게 생성할 수 있습니다. 

그러나 안드로이드 개발시에는 Dispatcher 생성에 딱히 신경쓸 필요가 없는 것이, 이미 생성되어 있기 때문입니다.

종류는 다음과 같습니다.

 

- Unconfined

- Main

- IO

- Default

 

Unconfined 는 말 그대로 제한을 받지 않는 Dispatcher 입니다. 유휴 Dispatcher 에 할당되어 해당 Context 위에서 수행됩니다. 실제로 Unconfined Dispatcher 를 통해 코루틴 작업을 수행하면 매번 다른 Dispatcher 를 이용하는 것이 확인됩니다.

 

Main 은 UI와 상호작용하는 작업에 사용하도록 권고되고 있습니다. UI 관련 작업은 MainThread 에서 수행되어야 하기 때문이죠. 해당 Dispatcher 를 이용하는 코루틴은 MainThread 에 탑재되어 작업을 수행합니다.

 

UI Objects 가 구동되고 있는 MainThread 에 국한되어 있는 Dispatcher 입니다. MainScopeFactory 를 통해서도 사용될 수 있다고 하네요.

CoroutineScope(Dispatchers.Main).launch {
	// do something
}

// 위처럼 사용하는 것이 일반적이지만, 다음과도 같이 사용할 수 있습니다.

MainScope().launch {
	// do something
}

 

IO 는 디스크 또는 네트워크 작업을 수행하는 코루틴을 위한 Dispatcher 입니다. 해당 Dispatcher 를 이용한 코루틴은 WorkerThread 에 탑재되어 작업을 수행하게 됩니다.

 

재미있는 사실이 하나 있습니다. Default Dispatcher 를 통해 수행하던 작업에 대해 withContext(Dispatchers.IO) 를 통한 컨텍스트 스위칭을 진행해도 쭉 Default Dispatcher 에서 진행이 됩니다. 

 

 

Default 는 많은 연산을 필요로 하는 작업, 정렬, JSON 파싱 등에 사용되는 경우가 많습니다. 보통 CPU 코어 수와 동일한 갯수의 스레드가 존재합니다.

 

CoroutineScope(Dispatchers.Default).launch {
	// do something
}

// 위처럼 사용하는 것이 일반적이지만, 다음과도 같이 사용할 수 있습니다.

CoroutineScope().launch {
	// do something
}

 


굉장히 많이 사용하고 있지만, 그다지 큰 관심을 주지 않았던 것인데, 이렇게 한 번 찬찬히 톺아보니 궁금한 점 투성이입니다. 관련된 기록이 늘어날 것 같습니다.