본문 바로가기

Kotlin

[Kotlin] Coroutine (2) - Use in Kotlin

 

안녕하세요.

코틀린에서 코루틴을 사용하는 방법에 대해 알아보겠습니다.


스케줄러의 코루틴 관리

스케줄러가 코루틴을 suspend & resume 해서 관리합니다.

 

suspend

현재 코루틴 실행을 일시 중지하고 모든 로컬 변수를 저장합니다.

 

resume

정지되었던 위치부터 정지된 코루틴을 재개합니다.


비동기 작업을 하고 싶으면 suspend 키워드를 함수 앞에 붙여주면 됩니다.

suspend fun doSomething() {
    ...
}

Dispatcher

Dispatcher는 코루틴이 실행되는 스레드 또는 스레드 풀을 관리하는 개념입니다.

Kotlin은 코루틴을 어떤 스레드에서 실행할지 정하는데에 사용할 수 있는 3가지 dispatcher를 제공합니다.

 

Dispatchers.Main

android 기본 스레드에서 코루틴을 실행할 때 사용합니다.

 

UI를 그리거나, 빠른 작업을 실행하기 위해서만 사용해야 합니다.

ex) suspend 함수 호출, LiveData 객체 업데이트

 

Dispatchers.IO

기본 스레드 외부에서 네트워크 I/O를 실행할 때 사용합니다.

ex) 파일에서 읽거나 쓰며 네트워크 작업을 할 때

 

Dispatchers.Default

기본 스레드 외부에서 CPU를 많이 사용하는 작업을 할 때 사용합니다.

ex) JSON 파싱

 

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

suspend fun printInMainThread() {
    println("Printed in the main thread")
}

suspend fun printInBgThread() {
    println("Printed in the background thread: ${Thread.currentThread().name}")
}

fun main() = runBlocking {
    println("Start main coroutine")

    // Main Dispatcher에서 실행되는 코루틴
    launch(Dispatchers.Main) {
        printInMainThread()
    }

    // IO Dispatcher에서 실행되는 코루틴
    launch(Dispatchers.IO) {
        printInBgThread()
        delay(1000) // 1초 동안 일시 중단
        printInBgThread()
    }

    // Default Dispatcher에서 실행되는 코루틴
    launch(Dispatchers.Default) {
        printInBgThread()
    }

    println("End main coroutine")
}

코루틴 실행

코루틴을 실행하는 방법으로는 2가지가 있습니다.

 

launch

호출자에게 결과를 반환하지 않습니다.

→ 반환값이 없는 일반적인 비동기 작업에 사용되며, 결과에 신경을 쓰지 않습니다.

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        doSomething1()
    }

    launch {
        doSomething2()
    }
}

suspend fun doSomething1() {
    delay(1000L)
    println("routine 1")
}

suspend fun doSomething2() {
    delay(500L)
    println("routine 2")
}

 

async

await 함수로 결과를 반환합니다.

→ 반환값이 있는 비동기 작업에 사용되며, 결과를 받아와 활용하는데 주로 사용합니다.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val task1 = async { doSomething1() }
    val task2 = async { doSomething2() }

    val result1 = task1.await()
    val result2 = task2.await()
    println("result : $result1 and $result2")
}

suspend fun doSomething1() : String {
    delay(1000L)
    return "routine 1"
}

suspend fun doSomething2() : String {
    delay(500L)
    return "routine 2"
}

코루틴 스코프

코루틴이 실행되는 범위를 나타내는 개념입니다.

여러 가지가 있지만, 안드로이드에서 자주 사용되는 것을 보겠습니다.

 

viewModelScope

ViewModel의 생명 주기에 맞춰 관리됩니다.

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MyViewModel : ViewModel() {

    fun performTask() {
        viewModelScope.launch {
            // viewModelScope 내에서 코루틴 실행
            delay(1000)
            println("Task completed")
        }
    }
}

 

lifecycleScope

액티비티 또는 프래그먼트의 생명 주기에 맞춰 관리됩니다.

import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MyFragment : Fragment() {

    fun performTask() {
        lifecycleScope.launch {
            // lifecycleScope 내에서 코루틴 실행
            delay(1000)
            println("Task completed")
        }
    }
}

Job

launch 또는 async로 만드는 각 코루틴은 Job 인스턴스를 반환합니다.

  • 각 코루틴을 고유하게 식별하기 위해
  • 수명 주기를 직접 관리하기 위해

Job 객체로 할 수 있는 메서드 중 2가지만 보겠습니다.

 

Join

특정 코루틴이 완료될 때까지 다른 코드 블록이나 코루틴이 대기할 수 있습니다.

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {

    // launch로 생성한 코루틴
    val job = launch {
        repeat(3) {
            delay(300)
            println("Job is working... $it")
        }
    }

    println("Main coroutine is doing something else")

    // job이 완료될 때까지 대기
    job.join()

    println("Main coroutine is finished")
}
Main coroutine is doing something else
Job is working... 0
Job is working... 1
Job is working... 2
Main coroutine is finished

 

cancel

코루틴을 취소하는 함수입니다.

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {

    // Job을 사용하여 코루틴 실행
    val job = launch {
        repeat(5) {
            println("Working... $it")
            delay(500)
        }
    }

    delay(1000)

    // Job을 취소하여 코루틴 중단
    job.cancel()

    println("Main coroutine is finished")
}
Working... 0
Working... 1
Main coroutine is finished

Reference

Kotlin 코루틴으로 앱 성능 향상  |  Android Developers

 

Kotlin 코루틴으로 앱 성능 향상  |  Android Developers

Kotlin 코루틴으로 앱 성능 향상 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Kotlin 코루틴을 사용하면 네트워크 호출이나 디스크 작업과 같은 장기 실행 작

developer.android.com

 

'Kotlin' 카테고리의 다른 글

[Kotlin] Sealed Class  (3) 2024.09.22
[Kotlin] Extension Function (확장 함수)  (0) 2024.09.10
[Kotlin] Null Safety  (0) 2024.07.29
[Kotlin] Coroutine (3) - 예외 처리  (1) 2023.12.01
[Kotlin] Coroutine (1) - 코루틴이란?  (0) 2023.11.30