Coroutines

    [Kotlin Coroutines] Log 를 사용한 Coroutines 디버깅

    로그를 사용한 디버깅의 필요성 Kotlin Coroutines는 같은 Coroutine Builder(launch, async 등) 의 중괄호 내부의 코드들이 다른 스레드에서 실행될 수 있다. 예를 들어 아래 코드에서 "task1 : start" 는 메인 스레드에서 실행되지만, "task1 : end"는 DefaultExecutor 스레드에서 실행된다. import kotlinx.coroutines.* fun main() = runBlocking { val task1 = launch(Dispatchers.Unconfined) { log("task1 : start") delay(100) log("task1 : end") } val task2 = launch { log("task2 : start") dela..

    [Kotlin Coroutines] IntelliJ 사용해 Coroutines 디버깅 하기

    디버깅을 하기 위한 준비 Kotlin Coroutines는 일시 중단 후에는 다른 스레드에서 실행될 수 있기 때문에 디버깅을 하기가 매우 어렵다. 이 글에서는 디버깅을 하기 어려운 예 중에 가장 간단한 예시를 제시할 것이다. 다음의 코드를 보자. import kotlinx.coroutines.* fun main() = runBlocking { launch(Dispatchers.Unconfined) { println("launch1 Working Thread : ${Thread.currentThread().name}") delay(100) println("launch1 Working Thread : ${Thread.currentThread().name}") } launch { println("launch2..

    [Coroutine Flow] flatMapMerge 을 사용해 flow 변환 동시 처리하기

    flatMapMerge는 무슨 역할을 하는가? flatMapConcat과 flatMapLatest는 flow에서 발행된 데이터를 변환할 때 발행된 순서대로 순차적으로 변환한다. 반대로 flatMapMerge는 변환을 병렬로 수행한다. 대부분의 연산이 flatMapConcat이나 flatMapLatest를 이용한 순차 처리에 해당하지만 들어오는 데이터들을 동시에 수집한 후 수집한 값들이 가능한 빨리 방출 될 수 있도록 병렬로 처리되어야 할 때가 있다. 예를 들어 비용 처리를 위해 수십개의 지출 데이터를 취합하여 합치는 작업을 할 경우 굳이 순차적으로 처리하지 않고 병렬로 처리되는 것이 빠를 것이다. flatMapMerge는 이러한 병렬 연산을 지원하기 위해 만들어진 연산자이다. flatMapConcat과 ..

    [Coroutine Flow] conflate를 이용해 최신 데이터 collect 하기

    collectLatest를 이용한 최신 데이터 collect의 한계점 그림1과 같이 데이터 발행 시간 사이의 간격보다 데이터를 처리하는 suspend fun이 수행하는 시간이 오래 걸릴 경우, 새로 들어온 데이터는 계속해서 소비되지 못한다. 즉 이런 상황에서 collectLatest를 쓸 경우 중간 데이터를 하나도 얻지 못하고 마지막 데이터만을 얻을 수 있다. 예를 들어 아래 그림2와 같이 데이터 발행에 0.1초가 걸리는데 데이터 소비에 1초가 걸릴 경우 하나도 소비가 안되고 마지막 데이터만이 소비된다. conflate을 이용해 최신 데이터 collect하기 이를 해결하는 방법은 간단하다. 한 번 시작된 데이터 소비는 끝날 때까지 하고 데이터 소비가 끝난 시점에서의 가장 최신 데이터를 다시 소비하는 것이..

    [Coroutine Flow] buffer 이용해 발행과 소비를 위한 Coroutine 분리하기

    collect에서 데이터 발행과 소비가 일어나는 방식 flow의 collect를 사용하면 하나의 Coroutine에서 발행과 소비가 같이 일어나기 때문에 데이터가 발행된 후 소비가 끝나고 나서 다시 다음 데이터가 발행된다. 즉 발행과 소비가 순차적으로 일어난다. 이를 그림으로 표현하면 다음과 같다. 하지만 이 방식은 매우 비효율적이다. 발행하는 쪽이나 소비하는 쪽의 delay를 미리 처리하지 않는다면 발행부와 소비부 양쪽에서 모두 delay가 생기기 때문이다. 예를 들어 다음과 같이 발행에 1초 소비에 3초가 걸리는 코드가 있다고 해보자. 그림2의 로그에서 볼 수 있듯이 collect를 사용하면 데이터를 발행하는데 1초 소비하는데 3초가 걸려서 총 4초가 발행과 소비에 사용된다. 즉, 발행에 지연(del..