코틀린 스터디

핫 데이터 소스와 콜드 데이터 소스

막이86 2024. 1. 4. 10:54
728x90

코틀린 코루틴을 요약한 내용입니다.

  • 채널은 값을 핫(hot) 스트림으로 가지지만, 콜드(cold) 스트림이 필요할 때가 있습니다.
  • 우리가 사용하는 대부분의 데이터 소스는 두 가지 종류로 구분할 수 있음
    • 컬렉션은 핫, Channel은 핫
    • Sequence와 자바의 Stream은 콜드, Flow와 RxJava 스트림은 콜드

핫 vs 콜드

  • 핫 데이터 스트림의 빌더와 연산은 즉각 실행
  • 콜드 데이터 스트림에서는 원소가 필요할 때 까지 실행되지 않음
  • fun main() { val l = builList { repeat(3) { add("User$id") println("L: Added User") } } val l2 = l.map { println("L: Processing") "Processed $it" } val s = sequence { repeat(3) { yield("User$it") println("S: Added User") } } val s2 = s.map { println("S: Processing") "Processed $it" } }
  • 콜드 데이터 스트림
    • 무한할 수 있다
    • 최소한의 연산만 수행
    • 메모리를 적게 사용 (중간에 생성되는 값을 보관할 필요가 없기 때문에)
  • Sequence는 원소를 지연 처리하기 때문에 더 적은 연산을 수행
    • 중간 연산은 이전에 만든 시퀀스에 새로운 연산을 첨가
    • 최종 연산이 모든 작업을 실행
  • 시퀀스의 처리 방식은 모든 중간 과정을 계산하고 모든 데이터 처리가 완료된 컬렉션을 반환하는 리스트의 처리 방식과는 다름
  • 리스트의 경우 원소의 처리 순서가 달라지며, 컬렉션 처리 과정에서 좀 더 많은 메모리를 필요로 하고, 더 많은 연산을 수행
    • 리스트는 원소의 컬렉션
    • 시퀀스는 원소를 어떻게 계산할지 정의한 것
    fun m(i: Int): Int {
    	print("m$i ")
    	return i * i
    }
    
    fun f(i: Int): Boolean {
    	print("f$i ")
    	return i >= 10
    }
    
    fun main() {
    	listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    		.map { m(it) }
    		.find { f(it) }
    		.let { print(it) }
    
    	println()
    	sequenceOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    		.map { m(it) }
    		.find { f(it) }
    		.let { print(it) }
    }
    
  • 핫 데이터 스트림
    • 항상 사용 가능한 상태 (각 연산이 최종 연산이 될 수 있음)
    • 여러 번 사용되었을 때 매번 결과를 다시 계산할 필요가 없음
    fun m(i: Int): Int {
    	print("m$i ")
    	return i * i
    }
    
    fun main() {
    	val l = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    						.map { m(it) }
    	
    	println(l)
    	println(l.find { it > 10 })
    	println(l.find { it > 10 })
     	println(l.find { it > 10 })
     
    	val s sequenceOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    					.map { m(it) }
    
    	println(s.toList())
     	println(s.find { it > 10 })
     	println(s.find { it > 10 })
     	println(s.find { it > 10 })
    }
    

핫 채널, 콜드 플로우

  • 플로우를 생성하는 가장 일반적인 방법은 produce 함수와 비슷한 형태의 빌더를 사용
    • 빌더가 바로 flow
    val channel = produce {
    	while (true) {
    		val x = computeNextValue()
    		send(x)
    	}
    }
    
    val flow = flow {
    	while (true) {
    		val x = computeNextValue()
    		emit(x)
    	}
    }
    
  • 두 빌더는 개념적으로는 동일, 채널과 플로우의 방식이 아주 다름
  • 채널은 핫이라 값을 곧바로 계산
    • 별도의 코루틴에서 계산을 수행
    • produce는 CoroutineScope의 확장 함수로 정의되어 있는 코루틴 빌더가 되어야 함
    • 소비되는 것과 상관없이 값을 생성한 뒤에 가지게 됨
    • 수신자가 얼마나 많은지 시경 쓰지 않음
    • 각 원소는 단 한 번만 받을 수 있기 때문에, 첫 번째 수신자가 모든 원소를 소비하고 나면 두 번째 소비자는 채널이 비어 있으며 닫혀 있다는 걸 발견
    private fun CoroutineScope.makeChannel() = produce {
    	println("Channel stared")
    	for (i in 1..3) {
    		delay(1000)
    		send(i)
    	}
    }
    
    suspend fun main() = coroutineScope {
    	val channel = makeChannel()
    	
    	delay(1000)
    
    	println("Calling channel...")
    	for (value in channel) {
    		println(value)
    	}
    
    	println("Calling again...")
    	for (value in channel) {
    		println(value)
    	}
    }
    
  • 플로우는 콜드 데이터 소스이기 때문에 값이 필요할 때만 생성
    • flow는 빌더가 아니면 어떤 처리도 하지 않음
    • 최종 연산이 호출될 때 원소가 어떻게 생성되어야 하는지 정의한 것에 불과
    • flow 빌더는 CoroutineScope가 필요하지 않음
    private fun makeFlow() = flow {
    	println("Flow started")
    	for (i in 1..3) {
    		delay(1000)
    		emit(i)
    	}
    }
    
    suspend fun main() = coroutineScope {
    	val flow = makeFlow()
    	
    	delay(1000)
    	println("Calling flow...")
    	flow.collect { value -> println(value) }
    	println("Consuming again...")
    	flow.collect { value -> println(value) }
    }
    

요약

  • 대부분의 데이터 소스는 핫이거나 콜드
  • 핫 데이터
    • 가능한 빨리 원소를 만들고 저장
    • 원소가 소비되는 것과 무관하게 생성
    • 컬렉션(List, Set)과 Channel이 있음
  • 콜드 데이터
    • 최종 연산에서 값이 필요할 때가 되어서야 처리
    • 중간 과정의 모든 함수는 무엇을 해야 할지만 정의
    • 연산은 최소한으로 수행, 무한정일 수 있음
    • Sequence, 자바의 Steram, Flow, RxJava 스트림
728x90

'코틀린 스터디' 카테고리의 다른 글

플로우의 실제 구현  (0) 2024.02.02
플로우란 무엇인가?  (1) 2024.01.04
셀렉트  (0) 2024.01.04
채널  (0) 2023.12.04
코루틴 스코프 만들기  (1) 2023.11.24