밍맹의 생각날 때 적는 블로그

[Android/Kotlin] 비동기 작업을 위한 Coroutine을 Araboza! (1) 본문

안드로이드

[Android/Kotlin] 비동기 작업을 위한 Coroutine을 Araboza! (1)

mingmaeng 2021. 1. 13. 21:39

안드로이드의 메인 스레드(=UI 스레드)의 작업량이 많아져 5초 이상의 대기시간이 걸리게 되면 ANR 에러를 일으키면서 앱이 종료됩니다.

그래서 메인 스레드에 부하가 들어가는 작업들은 최대한 다른 스레드에서 작업을 해줘야 하죠.

( 메인 스레드는 UI의 상태 변경에만 쓰이는 것이 제일 좋습니다.)

다른 스레드에서 작업을 하게 된다면 여러 개의 작업이 병렬적으로 동작합니다. 마치 옷 만드는 공장에서 옷감 만들기, 옷 만들기, 포장하기 등 모든 일을 하는 것에서 옷감 만들기 공장, 옷 만들기 공장, 포장하기 공장이 만들어져 각자의 일을 독립적으로 수행하게 되는 것과 비슷합니다.

 

안드로이드 스튜디오는 비동기적으로 로직을 처리하고 싶을 때 Handler와 Thread, 그리고 AshycTask를 제공했습니다.

그러나 사용하기도 꽤 까다롭고, 그나마 쉽게 사용할 수 있었던 AshycTask의 deprecated로 인해 비동기 로직을 대체할 무엇인가가 필요했습니다.

 

그래서 현재는 RxJava와 이번에 알아볼 Coroutine을 많이 사용하고 있습니다. Coroutine은 RxJava에 비해 러닝 커브가 그렇게 높지 않으며, 사용하기 쉽기 때문에 많은 분들이 애용하고 있습니다.
이번 포스팅은 Coroutine에 대한 개념과 간단한 사용법 몇 가지를 적어보려고 합니다.

 


Coroutine?

코루틴은 비동기적으로 실행되는 코드를 간소화하기 위해 Android에서 사용할 수 있는 동시 실행 설계 패턴입니다.

기존에 비동기 작업은 여러 개의 스레드를 생성하여 작업하였지만, 코루틴은 하나의 스레드 안에 여러 개의 코루틴을 

생성하여 작업합니다. 이와 같은 특성 때문에 '경량 스레드'라는 별칭이 붙어 있습니다.

 

코루틴의 이해를 돕기 위한 이미지

 

Scope

코루틴을 사용하기 위해선 코루틴의 제어 범위 및 실행 범위를 지정해주어야 합니다.

Scope는 제어 범위를 나타내며 GlobalScope와 CoroutineScope가 존재합니다.

GlobalScope는 프로그램 어디서나 제어, 동작이 가능한 범위이며

CoroutineScope는 Dispatcher라는 것을 지정하여 해당 제어 범위 내에서 제어 및 동작을 합니다.

간단 요약하자면 다음과 같습니다.

 

 

안드로이드에서 작업하실 때는 주로 CoroutineScope를 사용해주시면 됩니다.

GlobalScope를 사용하게 된다면 앱이 종료될 때까지 해당 코루틴을 실행시킬 수 있습니다.

그러나 Activity가 종료돼도 코루틴은 작업이 끝날 때까지 동작합니다.

 ex. Activity에서 이미지를 받고 있는데, 사용자가 해당 Activity를 종료한다면 이미지를 받는 작업은 불필요한 작업이 될 겁니다.

 

그렇다고 GlobalScope를 아예 금기시하는 건 아닙니다. 필요에 따라 적절하게 GlobalScope를 써주시면 됩니다. (화면과 무관하게 Service 작업 필요시 등등)

 

Dispatcher

코루틴을 사용할 때 동작할 스레드 타입을 지정해주어야 합니다. 이를 Thread Context라고 하는데, 해당 스레드 타입은 Dispatcher를 이용하여 지정해줍니다.

 

총 3가지의 Dispatcher가 존재하는데 하나씩 살펴보겠습니다.

 

  • Dispathcer.Main : 안드로이드의 메인 스레드. UI 작업은 반드시 여기서 처리되어야 합니다.
  • Dispatcher.IO : 디스크 또는 네트워크에서 데이터를 읽는 I/O 작업을 처리합니다.(서버 통신, Room 등)
  • Dispatcher.Default : 그 외 CPU 연산 작업들은 해당 스레드에서 처리합니다.

launch vs async

launch와 async는 코루틴을 생성하는 구문입니다. 람다 함수를 통해 비교적 간단하게 사용할 수 있습니다.

 

  • launch : 반환 값이 없는 Job 객체를 반환
  • async : 반환 값이 있는 Deffered 객체를 반환
CoroutineScope(Dispatcher.Default).launch{
	//코루틴에서 동작할 로직
    //반환값이 없는 Job 객체 반환
}

CoroutineScope(Dispatcher.Default).async{
	//코루틴에서 동작할 로직
    //반환값이 있는 Deffered 객체 반환
}

 


지금까지 대략적인 코루틴의 개념과 기초 내용들을 알아보았습니다.

글이 길어질 것 같아서 안드로이드에서 사용하는 방법 및 코루틴의 다양한 기능들은

다음 포스팅에 이어서 적도록 하겠습니다.

 

포스팅 자료 출처

- Kotlin 강좌 #최종화 - 코루틴을 통한 비동기 처리

- [Android][Kotlin] 코루틴(Coroutine) 사용해보기

- 안드로이드 - Kotlin Coroutine을 사용하는 방법

- 안드로이드 개발자 문서 Coroutine

Comments