Hot Stream은 열정적이라 데이터를 소비하는 것과 무관하게 원소를 생성하지만, Cold Stream은 게을러서 요청이 있을 때만 작업을 수행하며 아무것도 저장하지 않는다.

Cold StreamHot Stream의 차이점은 3가지로 말할 수 있다.

  1. 데이터가 생성되는 위치
  2. 생산자가 발행한 데이터를 동시에 여러 소비자들이 수신할 수 있는지 여부
  3. 스트림이 데이터를 생산한 시점

이해를 돕기위해 Cold Stream를 CD Player, Hot Stream을 Radio로 설명해보겠다.

Cold Stream

CD Player는 CD내부에 음악이 저장되어 있다.(데이터가 내부에서 생성)
CD Player는 사용자가 재생버튼을 눌러야지만 재생이 시작된다.(소비자가 소비를 시작할 때 데이터 생산)
동일한 음악을 가지고 있는 CD는 여러 존재하지만 사용자가 하나의 CD를 공유하고 있지는 않는다.(하나의 생산자에는 하나의 소비자가 존재)

Cold Stream는 데이터가 내부에서 생성된다.

Flow builder인 flow {}, flowOf(), asFlow() 등 모두 데이터가 내부에서 생성된다.

val coldStream: Flow<Int> = flow {
    //flow 내부에서 데이터 생성
    emit(1)
    emit(2)
}


val coldStream: Flow<Int> = flowOf(1, 2)
public fun <T> flowOf(vararg elements: T): Flow<T> = flow {
    for (element in elements) {
        //flow 내부에서 데이터 생성
        emit(element)
    }
}


val data = listOf(1, 2)
val coldStream: Flow<Int> = data.asFlow()
public fun <T> Iterable<T>.asFlow(): Flow<T> = flow {
    forEach { value ->
        //flow 내부에서 데이터 생성
        emit(value)
    }
}

flowOf()나 asFlow()의 내부 코드를 보면 flow()를 사용하고 있고 어찌됐든 flow() 내부에서 emit()을 통해 데이터를 발행하고 있다.

Cold Streamr는 소비자가 소비를 시작할 때 데이터를 생성한다.

val coldStream = flow<Int> {
    emit(1)
    emit(2)
}

coldStream.collect { // collet() 메서드 호출할 경우 flow{} 실행
    println(it)
}

flow는 소비를 시작하는 함수인 종단연산자(collect, fold, reduce, first등)가 호출되지 않으면 데이터를 생산하지 않는다. 물론 중간연산자(map, onEach, filter 등)도 종단연산자가 호출돼야지 실행된다.

Cold Stream은 하나의 생산자에 하나의 소비자만 존재한다.

val coldStream = flow<Int> {
    emit(1)
    emit(2)
}

coldStream.collect {
    println(it) // 1 2 수신
}

coldStream.collect {
    println(it) // 1 2 수신
}

flow를 여러 곳에서 collect할 수 있다. 그 떄 마다 flow{}이 실행되며 새로운 생성자들이 만들어진다. 이전 소비자들의 구독과는 독립적이다.

Cold Stream을 정리하자면,

  1. 데이터가 내부에서 생성된다.
  2. 데어터는 소비자가 소비를 시작할 때 생성된다.
  3. 하나의 생산자에는 하나의 소비자가 존재한다.


Hot Stream

앞서 Hot Stream을 radio에 비유해서 표현해보겠다고 말한적이 있다.
Radio는 방송국에서 프로그램을 제작하고.(데이터가 외부에서 생성) 청취자들에게 동시에 송신한다.(하나의 생산자에 다수의 소비자가 존재)
Radio는 청취자들의 청취여부와 상관없이 데이터를 계속 송신하고 있다. 청취자들은 청취를 시작한 순간부터 들을 수 있게 된다.(생산자가 소비자를 신경쓰지 않고 생산)

Hot Stream은 데이터가 외부에서 생성된다.

suspend fun main(): Unit = coroutineScope {
    val mutableSharedFlow = MutableSharedFlow<String>()

    launch {
        mutableSharedFlow.collect {
            println("#1 received $it")
        }
    }

    delay(1000)
    mutableSharedFlow.emit("Message1")
    mutableSharedFlow.emit("Message2")
}

// (1초 후)
// #1 received Message1
// #1 received Message2

Hot StreamsharedFlow 또한 flow와 마찬가지로 emit() 통해 데이터를 발행하는 것을 알 수있다.
그러나 flow와 달리 Flow Builder인 flow(), flowOf(), asFlow()처럼 안에서 데이터를 미리 생성하지 않고 외부에서 생성되는 것을 볼 수 있다.

Hot Stream은 하나의 생산자에 다수의 소비자가 구독할 수 있다.

suspend fun main(): Unit = coroutineScope {
    val mutableSharedFlow = MutableSharedFlow<String>()

    launch {
        mutableSharedFlow.collect {  // 소비자 1
            println("#1 received $it")
        }
    }

    launch {
        mutableSharedFlow.collect {  // 소비자 2
            println("#2 received $it")
        }
    }

    delay(1000)
    mutableSharedFlow.emit("Message1")
    mutableSharedFlow.emit("Message2")
}

// (1초 후)
// #1 received Message1
// #2 received Message1
// #1 received Message2
// #2 received Message2

이미 SharedFlow가 생성되어 있고 소비자 1소비자 2는 모두 같은 mutableSharedFlow를 구독하고 있다.
mutableSharedFlow가 데이터를 발행했을 때 구독중인 소비자 1소비자 2는 동일한 데이터를 수집한다.

Hot Stream은 생산자가 소비자의 소비를 신경쓰지 않고 생산한다.

suspend fun main(): Unit = coroutineScope {
    val mutableSharedFlow = MutableSharedFlow<String>()

    launch {
        repeat(3) {
            mutableSharedFlow.emit("Message$it")
            delay(1000)
        }
    }

    delay(2000)

    launch {
        mutableSharedFlow.collect {  // 소비자
            println("#1 received $it")
        }
    }
}
// (2초 후)
// #1 received Message2

Cold Stream인 flow에서는 collec()를 호출해야지만 flow() 내부의 데이터가 발행(생산)되었다.
그러나 Hot Stream인 SharedFlow는 소비자가 collect(), 구독을 하지 않아도 emit()을 통해 데이터를 발행(생산)하고 있다.
당연히 발행한지 2초 이후에 데이터를 수집했으므로 #1 received Message2의 결과만 출력이 되는 것을 확인할 수 있다.

Hot Stream을 정리하자면,

  1. 데이터가 외부에서 생성된다.
  2. 하나의 생산자에 다수의 소비자가 존재한다.
  3. 생산자가 소비자의 소비를 신경쓰지 않고 생산 (소비자는 소비를 시작한 시점부터 생산된 데이터를 소비하기 시작한다.)

Reference

Cold Flow와 Hot Flow