[android/kotlin] Coroutine(코루틴)#2

Falco·2022년 9월 26일
0

Android

목록 보기
28/55

코루틴이란??

백그라운드 작업을 위한 쓰레드를 직접 만들고 사용할 수도 있지만, Kotlin에서 멀티테스킹을 더 유연하고 쉽게 관리할 수 있는 코루틴을 제공한다.

코루틴은 비동기적이고 non-blocking한 프로그래밍을 제공하는 경량스레드이다.

많은 리소스가 필요한 스레드

  • 스레드를 만들고 전환하고 관리하는 데는 많은 메모리가 필요하다.
  • 또한 Thread간의 전환 시에도 OS 커널 디스패처를 수반하며 이는 많은 자원을 소모한다.
  • 여러 스레드가 전환할 때 스레드가 실행되는 정확한 시간과 스레드가 일시중지되는 시점은 개발자가 제어할 수 없다. 스레드를 직접 사용할 때 항상 예측 가능한 출력이 나오지 않는다.

코루틴은

  • OS에 관여를 하지 않기에 비용이 저렴하다.
  • 코루틴의 주요 기능 중 하나는 상태를 저장하여 중단했다가 재개할 수 있다.
  • 자기가 원할 때 중단하고 예측 가능한 결과를 기대할 수 있다.
  • 기존 실행 중인 스레드를 차단하지 않고 정지 기능을 지원함으로 메모리를 절약한다.

키워드

CoroutineScope

코루틴이 실행되는 범위

ViewModelScope, LifecycleScope, GlobalScope 등 코루틴이 빌드되고 실행되는 범위를 의미한다.

CoroutineContext

코루틴의 실행 동작에 대해 정의하고 제어한다.

  • Job : 코루틴의 상태를 가지고 있으며 제어한다.

    join(), start(), cancel(), cancelAndJoin() 등 함수를 코루틴을 제어할 수 있는 함수를 지원한다.
    Job 은 코루틴의 핸들의 역할을 수행한다. 각 코루틴을 식별하고 수명주기를 관리할 수 있다.

  • Dispatcher : 코루틴을 어떤 스레드에서 동작할 것인지를 정의

    Dispatcher.Main - 메인 스레드에서 동작(UI쓰레드)
    Dispatcher.IO - 네트워크 / 디스크(파일) 작업에 사용하는 방식
    Dispatcher.Default - CPU사용량이 많은 작업에 수행
    IO, Default는 백그라운드 작업

   val job = CoroutineScope(DisPatchers.IO).launch {
      // ...
    }

	job.join()      // 작업이 완료되기까지 대기
	job.cancel() // 작업 취소

코루틴빌더 (CoroutineBuilder)

CoroutineScope의 확장함수로써 코루틴을 만들고 실행한다.

  • launch : Job 객체를 반환하며 결과값을 반환하지 않는다.

    실행 후 결과 값이 필요없는 작업을 수행한다.
CoroutineScope(Dispatchers.Main).launch {
    // 결과값이 필요없는 작업
}
  • async : Deferred<T>객체를 반환하며 결과값을 반환한다. 결과값은 <T>자료형을 뛴다.

suspend fun getValue(): Double {
    delay(3000)
    return Math.random()
}

suspend fun main() {
	val num1 = async { getValue() }
    val num2 = async { getValue() }
    println("result of num1 + num2 is ${num1.await() + num2.await()}") // result of num1 + num2 is 1.4320332550421415
}

await(), awaitAll()함수를 사용하여 코루틴 작업의 최종 결과값을 반환한다.
axios의 Promise와 동일하게 작동

  • withContext : async와 동일하게 결과값을 반환하며, await()를 호출할 필요가 없다.

    코루틴의 내부나 suspend함수 내에서 사용이 가능하며 코드내에서 코루틴의 세부적인 제어를 할 수 있다.
    콜백함수의 도입 없이 스레드 풀을 제어할 수 있다.

    * 마지막 줄의 값이 반환된다.
    * withContext가 끝나기 전까지 해당 코루틴은 일시정지 된다.

중요: 일반적으로 suspend 함수는 기본 스레드에서 작동한다.
디스크에서 읽기 또는 디스크에 쓰기, 네트워크 작업 실행, CPU 집약적인 작업 실행 등과 같은 기본적인 안전이 요구되는 withContext()는 항상 suspend 함수 내에서 사용해야 한다.

suspend fun main() = withContext(Dispatchers.Main) { 	// Dispatchers.Main
	val num = withContext(Dispatcher.IO) { getValue() } // Dispatchers.IO
    print(num) 											// Dispatchers.Main
}

suspend fun fetchDocs() {                             // Dispatchers.Main
    val result = get("https://developer.android.com") // Dispatchers.IO for `get`
    show(result)                                      // Dispatchers.Main
}

suspend fun get(url: String) = withContext(Dispatchers.IO) { /* ... */ }
  • suspend function

    정지가능한 함수를 의미한다.

반드시 코루틴 내에서 실행되어야 하며, 코루틴의 실행이 중단되거나 재개될 수 있기 때문에 suspend함수 내에서 코루틴이 실행되어야 한다.

참고 자료 :

https://jaejong.tistory.com/61

https://0391kjy.tistory.com/49

https://developer.android.com/kotlin/coroutines?hl=ko

https://developer.android.com/codelabs/basic-android-kotlin-training-introduction-coroutines?hl=ko#3

https://kotlinlang.org/docs/coroutines-guide.html

profile
강단있는 개발자가 되기위하여

0개의 댓글