본문 바로가기
Kotlin&Java/Coroutine

[Kotlin] 안드로이드에서 Coroutine 사용하기

by 굿햄 2023. 1. 18.

Kotlin Coroutine 이해하기 3부

의존성 추가

 Coroutine 사용을 위해 build.gradle(:app) 에 의존성을 추가한다.

 

Kotlin/JS 나 Kotlin/Native를 멀티플랫폼을 위한 설명은 아래 사이트에서 확인할 수 있다.

https://github.com/Kotlin/kotlinx.coroutines

 

코루틴의 일반적인 사용 방법

Coroutine(코루틴)은 Asynchronous/Non-Blocking Programming을 제공하는 Lightweight Thread(경량 스레드)이다.

 

기본적인 사용 문법은 Context(Job + Dispatcher)로 Scope를 만든 뒤, Builder를 사용하여 Coroutine을 실행하는 것이다.

이 세 가지의 용도는 아래에서 소개한다.

CoroutineScope 개념

코루틴의 실행 범위를 정의하며, Coroutine Builder(코루틴 빌더) launch 또는 async를 사용하여 만든 코루틴을 추적한다.

진행중인 코루틴은 cancel 함수로 취소 가능하다.

 

Android Jetpack 덕분에 Custom Scope(커스텀 스코프)를 작성할 필요없이 lifecycle에 따라 동작하므로 이미 만들어진 스코프를 사용하는 것을 권장한다.

 

Scope 함수의 파라미터로 Job과 Dispatcher를 지정할 수 있으나 이는 후에 설명한다.

 

따로 지정하지 않는다면 Dispatcher.Default이 디폴트이나 안드로이드에서는 Dispatcher.Main이 기본값이다.

관련 코드: https://github.com/androidx/androidx/blob/androidx-main/lifecycle/lifecycle-runtime-ktx/src/main/java/androidx/lifecycle/Lifecycle.kt

 

CoroutineScope 종류

CoroutineScope(Job + Dispatcher): 커스텀 스코프, cancel 함수 호출을 통해 제어를 해야한다.

객체를 생성하기 때문에, 호출한 객체가 메모리에서 해제되면 파괴된다.

 

GlobalScope: 글로벌 스코프, 싱글톤 객체로 앱이 종료될 때 까지 동작한다.

 

ViewModelScope: AAC ViewModel을 대상으로 ViewModel이 삭제되면 자동으로 취소된다.

 

LifeCycleScope: 각 LifeCycle 객체에 정의되며, LifeCycle이 끝날 때 제거된다.

 

- Activity에서의 사용

-Fragment에서의 사용

 

Coroutine Context 개념

코루틴 컨텍스트에는 코루틴의 동작을 정의할 수 있는 4가지 요소를 전달할 수 있다.

  • Job: 코루틴의 수명 주기를 제어합니다.
  • CoroutineDispatcher: 적절한 스레드에 작업을 전달합니다.
  • CoroutineName: 디버깅에 유용한 코루틴의 이름입니다.
  • CoroutineExceptionHandler: 포착되지 않은 예외를 처리합니다.

Coroutine Context - Dispatcher 종류

 앞서 Java에서 Thread Pool을 만드는 방법에 대해 살펴보았다.

Kotlin의 Coroutine(코루틴)에서는 디스패처를 이용하여 코루틴 실행에 사용되는 스레드를 자동으로 관리한다.

  • Dispatchers.Main - 이 디스패처를 사용하여 기본 Android 스레드에서 코루틴을 실행합니다. 이 디스패처는 UI와 상호작용하고 빠른 작업을 실행하기 위해서만 사용해야 합니다. 예를 들어 suspend 함수를 호출하고 Android UI 프레임워크 작업을 실행하며 LiveData 객체를 업데이트합니다.
  • Dispatchers.IO - 이 디스패처는 기본 스레드 외부에서 디스크 또는 네트워크 I/O를 실행하도록 최적화되어 있습니다. 예를 들어 회의실 구성요소를 사용하고 파일에서 읽거나 파일에 쓰며 네트워크 작업을 실행합니다.
  • Dispatchers.Default - 이 디스패처는 CPU를 많이 사용하는 작업을 기본 스레드 외부에서 실행하도록 최적화되어 있습니다. 예를 들어 목록을 정렬하고 JSON을 파싱합니다.

CoroutineBuilder 개념

CoroutineBuilder(코루틴 빌더) 확장함수는 CoroutineContext를 상속해 구성요소와 취소를 전파한다.

코루틴 안에서 suspend 함수나 코루틴을 시작할 수 있다.

CoroutineBuilder 종류

  • launch - 이 함수는 새 코루틴을 시작하고 호출자에게 결과를 반환하지 않으며 반환되는 객체는 Job이다.
Job은 Coroutine Handle(코루틴 핸들)로 'launch' 및 'async'로 만드는 코루틴은 Job인스턴스를 반환한다.
join 함수를 통해 코루틴 동작이 끝날 때 까지 대기하거나, cancel 함수를 통해 코루틴을 종료하는 등의 용도로 사용할 수 있다.

아래는 실제로 화자가 사용하는 코드 중 일부이다.

 

  • async - 이 함수는 새 코루틴을 예약하고 Deferred을 반환하며, await라는 정지 함수로 결과를 반환한다.
Deferred 객체를 이용하여 코루틴 블록에서 계산된 결과값을 반환 받을 수 있다.
await는 정지 함수로 코루틴 내부에서만 사용할 수 있다.

async의 경우 코루틴 내에서 예약된 작업으로 동시 처리가 필요할 때 주로 사용한다.

이에 대한 내용은 아래 Parallel decomposition(병렬 분해)에 사용방법을 서술한다.

 

Coroutine suspend

suspend 함수는 suspend 함수 안 또는 코루틴 안에서 실행할 수 있는 함수이다.

의미 그대로 코루틴 실행을 일시중지 가능하며, 강의 1부에서 보았듯 작업을 대기하는 동안(delay 함수나 Network 응답을 기다리는 등) 같은 스레드 내의 또 다른 코루틴이 수행되는 것을 가능하게 한다.

withContext()

withContext는 그 자체로 정지 함수이며, 데이터베이스 읽기 또는 네트워크 요청 등 Main Thread Pool(메인 스레드 풀)에서 백그라운드 스레드의 동작이 필요한 경우에 용이하다.

기본 스레드에서 실행되었지만, withContext를 통해 백그라운드에서 안전하게 호출이 가능하다.

 

Parallel decomposition (병렬 분해)

Suspend 함수 내에 있는 코루틴은 함수가 반환되면 중지되므로, 코루틴이 중지 되기 전에 처리가 완료되도록 보장해야 할 필요가 있다.

AwaitAwaitAll 두 가지 방식으로 선언이 가능

withTimeout & withTimeoutOrNull

코루틴 블록 내에서 네트워크 응답 시간에 제한을 둘 때 주로 사용하며, withTimeout(float)은 시간 초과 시 TimeoutCancellationException을 throw하고,

withTimeoutOrNull(float)을 사용하면 시간 초과 시 Null을 반환한다.

runBlocking

코틀린에서는 사용하지 않는 것을 권장한다.

Parameter로 CoroutineContext와 suspend 함수를 전달 받으며, 스레드를 Blocking(블로킹)하여 결과값을 반환한다.

 


이후 CoroutineExceptionHandler를 통한 에러처리와

Channel에 대한 내용은 Flow와 함께 부가적으로 설명할 예정이다.


이상 잘못된 부분이 있거나 추가 설명이 필요한 부분은 댓글로 남겨주시면 감사드리겠습니다.


ⓒ 굿햄 2022. daryeou@gmail.com all rights reserved.

'Kotlin&Java > Coroutine' 카테고리의 다른 글

[Kotlin] Coroutine vs Thread  (0) 2023.01.18
[Kotlin] Coroutine(코루틴) Thread란 무엇인가  (3) 2023.01.17

댓글