💌 [Android/Kotlin] 코루틴 (Coroutine)

📌 코루틴이란?

- "비동기 경량 스레드"

  • 예전에는 ANR (Activity Not Response) 오류를 해결하기 위해 스레드-핸들러나 AsyncTast를 이용했다.
    하지만 API 30 에서 deprecated 되었고 코루틴 이용을 권장한다.
  • "Co: 함께" + "routine: 작업 처리단위" = "Coroutine : 어떤 작업을 함께 처리한다."
  • 비동기 처리 방식과 같다.
    일반적인 스레드는 자유롭게 제어가 힘들고 구현도 복잡하다.
    그에 비해 코루틴은 가볍고 많은 기능을 제공한다.

💜 장점

  • 경량
  • 메모리 누수 감소
  • 취소 등 다양한 기능
  • 제트팩 라이브러리 적용

📌 Thread 2개의 Context 에 Coroutine 실행

Thread Blocking 없이 실행가능

📌 CoroutineContext

  • 코루틴 처리를 어떻게 할 것 인지에 대한 요소들의 집합.
  • CoroutineContext 요소
    Dispatcher : 코루틴을 처리할 스레드를 Setting 하고 할당하는 역할.
    Job : 생성된 코루틴을 컨트롤. (생명 주기, 부모 자식 관계 정리 및 관리)

💜 Coroutine Dispatcher

  • 코루틴을 스레드에 배분하는 역할을 담당한다.
  • 스레드 풀에서 스레드를 하나 할당해 코루틴을 배당한다.

스레드 풀 생성

fun main(){
    // Thread Pool 에서 Dispatcher 생성
    val threadPoolDispatcher = newFixedThreadPoolContext(5, "Thread 1")
   
   // 싱글 Thread에서 Dispatcher 생성
    val singleThreadDispatcher = newSingleThreadContext("Thread 2")
}

- 코루틴은 스레드풀을 생성하지만 직접 제어하지는 않고 오직 Dispatcher 를 통해서만 제어 가능.

💜 Dispatcher 종류

- Dispatchers.Main

: Android Main(UI) Thread에서 Coroutine을 실행하는 Dispatcher
반드시 UI 와 상호작용하기 위해서만 사용

- Dispatchers.IO

: File Input/Output , Network IO, Parser 작업에 최적화된 Dispatcher

- Dispatchers.Default

: CPU 사용량이 많은 작업에 사용
대규모 Sorting, Graphics Rendering 등

- Dispatchers.Unconfined : 특수한 상황에서 코루틴을 실행 (사용을 권장하지 않음)

📌 앱 수준의 gradle 추가

// 코루틴 사용
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")

📌 CoroutineScope

  • 코루틴이 실행되는 범위를 생성.
  • 다양한 Scope 확장 함수 (= Coroutine Builder)를 이용하여 코루틴을 만든다.

🤍 Coroutine Builder

  • launch

    : 결과값이 없는 코루틴.
    Job 객체를 리턴. 코루틴 관리만.
  • async

    : 결과값이 있는 코루틴.
    Defferred 로 감싸서 값 리턴.
  • withContext()

    : T 반환(결과값 T 를 그대로 반환하는 코루틴)
  • runBlocking()

    : T (코루틴 완료할 때 까지 스레드를 점유)
  • actor()

    : SendChannel
  • produce()

    : ReceiveChannel

-> 코루틴 빌더는 일반적으로 launch / async 를 제일 많이 사용.

📌 Coroutine Job 함수

  • start : 현 코루틴의 상태를 알아내어 동작 중 = true, 준비/종료 = false
  • join : 현 코루틴이 종료되기를 기다림, async Deferred의 await 와 같은 역할.
  • cancel : 현 코루틴을 즉시종료 (Thread의 interrupt 와 같은 역할).
  • cancelAndJoin : 현 코루틴을 종료하고 대기.
  • cancelChildren : 현 Coroutine Scope 내에 작성한 자식 코루틴들을 종료.
    부모 코루틴은 종료되지 않음.

💜 launch

// 현재 Thread 를 블럭 시키고 종료될 때 까지 대기 (안드로이드에서 신중하게 사용)
runBlocking { 
  		// 새로운 코루틴을 시작하고 Job 객체획득
        val job: Job = launch { 
            delay(3000L)
            println(1)
        }
        println(2)
        job.join() // 자식 코루틴이 종료되기를 기다림
        println(3) // 코루틴 종료 후 다시 시작
}

💜 async

CoroutineScope(Dispatchers.Main).launch {

  				// async 로 Boolean 결과값 반환
                val deferred: Deferred<Boolean> = async(Dispatchers.IO) { 
                    val data = listOf(1,2,3,4,5)
                    if (data.contains(2)) {
                        true
                    } else false
                }

  				// async 작업이 완료 되고 난 후 호출.
                val result = deferred.await() 
                println(result)

            }
  • await() 메소드를(멈춤 기능) 사용하려면 반드시 코루틴 블럭이나 suspend function 을 선언하여야 한다.

  • suspend function 함수는 코루틴 블럭, suspend function 함수 내부에서만 사용 할 수 있음.

공식문서 : https://developer.android.com/kotlin/coroutines?hl=ko
https://kotlinlang.org/docs/coroutines-guide.html

profile
Android Developer..+ iOS 슬쩍 🌱 ✏️끄적끄적,,개인 기록용 👩🏻‍💻

0개의 댓글