Kotlin

Coroutine withContext 를 이용한 await 처리

dev_roach 2022. 7. 11. 00:16
728x90

우리가 코루틴을 사용할때 보통 일정한 값을 기다려야 할때 아래와 같이 runBlocking 을 이용할 수도 있다.

fun test() = runBlocking {
    launch {
        // Some Api Calls
        println("hello, ")
    }
    return@runBlocking "ApiCalls Result"
}

fun main() {
    println(test())
}

위와 같이 작성하면 어떻게 될까? runBlocking 에서 한가지 알아야 할 점이 있는데, runBlocking 은 처음에 자신만의 Thread 를 고정시켜버린다. 따라서 아래와 같이 Thread 이름을 출력하는 형태로 코드를 작성해서 확인해보면 결과는 아래와 같다.

fun test() = runBlocking {
    launch {
        println("${Thread.currentThread().name} Launch 1")
        // Some Api Calls
        println("hello, ")
    }
    launch {
        println("${Thread.currentThread().name} Launch 2")
    }
    return@runBlocking "ApiCalls Result"
}

fun main() {
    println(test())
}
main Launch 1
hello, 
main Launch 2
ApiCalls Result

보면 main 스레드를 사용하고 있음을 알 수 있다. 그렇다면 어떻게 해야 위의 코드를 여러개의 Thread 로 처리를 시킬 수 있을까?

withContext 사용

suspend fun test() = withContext(Dispatchers.IO) {
    launch {
        println("${Thread.currentThread().name} Launch 1")
        delay(1000)
        // Some Api Calls
        println("hello, ")
    }
    launch {
        delay(100)
        println("${Thread.currentThread().name} Launch 2")
    }

    launch {
        delay(500)
        println("${Thread.currentThread().name} Launch 3")
    }

    return@withContext "ApiCalls Result"
}

suspend fun main() {
    println(test())
}

위와 같이 withContext 를 사용하면 test() 함수가 종료되기 전까지 (여기서는 return 하기 전까지) test 함수는 suspend 된다. 즉, 우리가 suspension 하게 해당 함수를 사용할 수 있다는 점이다. 따라서 우리가 async.. await 과 같이 함수의 호출값을 리턴받고 기다려야 한다면, withContext 를 사용하는 것이 좋다. 한번 Thread Name 을 확인해보자.

DefaultDispatcher-worker-3 Launch 1
DefaultDispatcher-worker-4 Launch 2
DefaultDispatcher-worker-4 Launch 3
hello, 
ApiCalls Result

 

처음 코드와 다르게 여러종류의 Thread 가 이용됬음을 알 수 있다. 따라서 좀 더 CPU 가 효율적으로 일 할 수 있다는 것이다. runBlokcing 은 최초 보유된 Thread 를 Blocking 시키지만, withContext 는 Thread 를 Blocking 시키지 않고, suspend 시킨다. 이 차이는 무척 큰 차이이므로, 함수의 종료를 기다려야 하는 상황에서 withContext 를 사용하는 것이 좋을 때가 많다.

생각해보면 좋을 점

withContext, runBlocking 모두 어찌 보면 순차적으로 코드를 실행시키기 위해서 작성하는 코드이다. 어쩔 수 없을땐 위와 같이 사용해도 좋지만, 다만 충분히 순차적이지 않아도 되는 부분을 withContext 로 작성하지 않도록 조심하도록 하자

728x90

'Kotlin' 카테고리의 다른 글

Kotlin) Channel 을 이용한 Actor Model 구현  (0) 2022.07.15
Kotlin Coroutine) Channel  (0) 2022.07.15
코드스피츠 6강) 코루틴  (0) 2022.07.07
코루틴 빌더 예외처리  (0) 2022.07.07
CoroutineScope 과 Runblocking 의 차이  (0) 2022.07.05