Groo

buffer를 활용하여 발행자와 소비자의 Coroutine 분리 본문

프로그래밍 언어/Kotlin

buffer를 활용하여 발행자와 소비자의 Coroutine 분리

김주엽 2022. 4. 2. 20:56

아래 내용은 모두 해당 원글을 기반으로 요약정리한 내용입니다.

그림은 저자가 직접 제작한 것임을 알려드립니다. (출처: Kt World)


Flow의 collect를 사용하면 하나의 Coroutine에서 발행과 소비가 함께 일어난다.

데이터를 발행하고 해당 데이터를 소비했으면 그 후에 다음 데이터가 발행된다, 이처럼 발행과 소비는 동기적으로 진행된다.

 

val bankFlow = flow {
    for (num in 1..50) {
        emit(num)
        delay(1000) // 은행 직원 휴식 시간
    }
}

fun visitBank() {
    lifecycleScope.launch {
        bankFlow.onEach {
            println("${it}번 고객님 차례입니다.")
        }.collect {
            delay(5000) // 통장 개설 소요 시간
            println("${it}번 고객은 창구에 방문하여 통장 개설을 마쳤다.")
        }
    }
}

// 1번 고객님 차례입니다.
// 1번 고객은 창구에 방문하여 통장 개설을 마쳤다.
// 2번 고객님 차례입니다.
// 2번 고객은 창구에 방문하여 통장 개설을 마쳤다.
// 3번 고객님 차례입니다.
// 3번 고객은 창구에 방문하여 통장 개설을 마쳤다.
...

이런 구조는 상황에 따라 비효율적일 수 있다.

발행자와 소비자가 각각 지연이 생기면 서로가 서로를 기다릴 수 밖에 없다.

 

buffer를 활용하면 발행자와 소비자의 Coroutine을 분리할 수 있다.

즉, 발행은 발행대로 소비는 소비대로 일어나기 때문에 서로가 이전처럼 현재 상태 정보를 공유할 필요가 없다.

 

val bankFlow = flow {
    for (num in 1..50) {
        emit(num)
        delay(1000) // 신규 대기표 생성 시간
    }
}

fun visitBank() {
    lifecycleScope.launch {
        bankFlow.onEach {
            println("${it}번 고객님이 대기표를 뽑았다.")
        }.buffer().collect {
            delay(5000) // 통장 개설 소요 시간
            println("${it}번 고객은 창구에 방문하여 통장 개설을 마쳤다.")
        }
    }
}

// 1번 고객님이 대기표를 뽑았다.
// 2번 고객님이 대기표를 뽑았다.
// 3번 고객님이 대기표를 뽑았다.
// 4번 고객님이 대기표를 뽑았다.
// 5번 고객님이 대기표를 뽑았다.
// 1번 고객은 창구에 방문하여 통장 개설을 마쳤다.
// 6번 고객님이 대기표를 뽑았다.
// 7번 고객님이 대기표를 뽑았다.
// 8번 고객님이 대기표를 뽑았다.
// 9번 고객님이 대기표를 뽑았다.
// 10번 고객님이 대기표를 뽑았다.
// 2번 고객은 창구에 방문하여 통장 개설을 마쳤다.
...

문제 상황에 맞게 Flow의 발행자와 소비자의 Coroutine을 관리하면 되겠다.


이렇게 buffer를 활용하여 Flow의 발행자와 소비자의 Coroutine을 분리시키는 방법에 대해서 알아봤다.

이제 오늘 하루를 마무리 하자 🫡

Comments