flowOn과 buffer: 컨텍스트와 백프레셔
flowOn으로 방출 컨텍스트를 변경하고 buffer로 백프레셔에 대비해 방출 값을 버퍼링해 보세요.
flowOn과 buffer: 컨텍스트와 백프레셔은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
플로우 컨텍스트
기본적으로 플로우는 collect를 호출하는 코루틴의 컨텍스트에서 실행됩니다. 변경하지 않는 한 생산자와 소비자의 디스패처는 동일합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
println("emit on: ${Thread.currentThread().name}")
emit(1)
}.collect {
println("collect on: ${Thread.currentThread().name}")
}
}flowOn으로 상류 컨텍스트 변경하기
flowOn(dispatcher)은 지정한 디스패처에서 상류 플로우(체인에서 그 연산자보다 위에 있는 모든 부분)를 실행하고, 수집은 호출자의 디스패처에서 계속 실행합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
println("emit: ${Thread.currentThread().name}")
emit(1)
}.map {
println("map: ${Thread.currentThread().name}")
it * 2
}.flowOn(Dispatchers.Default) // above runs on Default
.collect {
println("collect: ${Thread.currentThread().name}")
}
}체인에서 flowOn 여러 번 사용하기
flowOn은 여러 번 사용할 수 있습니다. 각 flowOn은 이전 flowOn까지 바로 위에 있는 연산자에 영향을 줍니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow { emit(1) }
.map { it + 1 }.flowOn(Dispatchers.IO) // map runs on IO
.map { it * 2 }.flowOn(Dispatchers.Default) // this map runs on Default
.collect { println("Result: $it") } // collect on Main (runBlocking)
}백프레셔 문제
생산자가 수집기에서 처리할 수 있는 속도보다 빠르게 값을 방출하면 값이 대기열에 쌓입니다. 버퍼링이 없으면 생산자가 기다리게 됩니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val time = System.currentTimeMillis()
flow {
repeat(3) { i ->
delay(100) // fast producer
emit(i)
}
}.collect {
delay(300) // slow consumer
println("Got $it in ${System.currentTimeMillis() - time}ms")
}
}buffer() 연산자
buffer()는 별도의 코루틴에서 생산자와 소비자를 동시에 실행하고, 방출된 값을 채널에 버퍼링합니다. 생산자는 소비자를 기다리지 않습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val time = System.currentTimeMillis()
flow {
repeat(3) { i -> delay(100); emit(i) }
}.buffer() // producer and consumer run concurrently
.collect {
delay(300)
println("Got $it in ${System.currentTimeMillis() - time}ms")
}
}buffer 용량
buffer(capacity)는 채널 버퍼의 크기를 설정합니다. 버퍼가 가득 차면 생산자가 일시 중단됩니다(백프레셔). 기본 용량은 64입니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
flow { repeat(5) { emit(it) } }
.buffer(Channel.RENDEZVOUS) // 0: producer waits
// .buffer(Channel.BUFFERED) // default: 64
// .buffer(Channel.UNLIMITED) // unbounded
.collect { delay(50); println(it) }
}최신 값만 유지하는 conflate()
conflate()는 수집기가 느릴 때 중간 값을 버리고 가장 최근에 방출된 값만 유지합니다. UI 상태에 유용합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
repeat(5) { i -> emit(i); delay(50) }
}.conflate()
.collect { i ->
delay(150)
println("Collected: $i") // skips some values
}
}느린 수집기에 collectLatest 사용하기
collectLatest는 새 값이 도착하면 현재 수집 블록을 취소하고 최신 값으로 다시 시작합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit(1); delay(50)
emit(2); delay(50)
emit(3)
}.collectLatest { value ->
println("Processing $value")
delay(100) // gets cancelled if new value arrives
println("Done $value") // only prints for last value
}
}flowOn + buffer 패턴
flowOn과 buffer를 결합하십시오. IO(네트워크/디스크)에서 생산자를 실행하고, 결과를 버퍼링한 다음, Main에서 수집합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun fetchItems(): Flow<String> = flow {
repeat(3) { i ->
delay(100) // simulate IO
emit("item-$i")
}
}.flowOn(Dispatchers.IO).buffer(10)
fun main() = runBlocking {
fetchItems().collect { println("UI: $it") }
}동시 생산자에 channelFlow 사용하기
channelFlow는 채널을 기반으로 하는 플로우를 생성하여 빌더 내부에서 여러 코루틴이 동시에 값을 방출할 수 있게 합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun concurrentFlow(): Flow<Int> = channelFlow {
launch { send(1) }
launch { send(2) }
launch { send(3) }
}
fun main() = runBlocking {
concurrentFlow().collect { println(it) }
}알맞은 전략 선택하기
요약하면, 컨텍스트 전환에는 flowOn, 처리량 향상에는 buffer, 최신 UI 값만 유지하려면 conflate, 오래된 처리를 취소하려면 collectLatest를 사용하십시오.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
// Guidelines:
// CPU-heavy production -> flowOn(Dispatchers.Default)
// IO-heavy production -> flowOn(Dispatchers.IO)
// Slow consumer -> buffer()
// UI state updates -> conflate() or StateFlow
// Search/autocomplete -> collectLatest or flatMapLatest
fun main() = runBlocking { println("Choose the right strategy!") }빠른 확인
플로우 체인에서 flowOn은 무엇에 영향을 줍니까?
복습
flowOn은 상류 작업을 다른 디스패처로 이동합니다. buffer는 처리량을 높이기 위해 생산자와 소비자를 분리합니다. conflate는 중간 값을 버립니다. collectLatest는 새 값이 도착하면 느린 처리를 취소합니다.
AI 튜터와 함께 Kotlin을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 51
- 레슨
- 203
자주 묻는 질문
“flowOn과 buffer: 컨텍스트와 백프레셔” 강의는 무료인가요?
네 — “flowOn과 buffer: 컨텍스트와 백프레셔” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“flowOn과 buffer: 컨텍스트와 백프레셔”에서 뭘 배우나요?
flowOn으로 방출 컨텍스트를 변경하고 buffer로 백프레셔에 대비해 방출 값을 버퍼링해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“flowOn과 buffer: 컨텍스트와 백프레셔” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Flow 연산자: map, filter, transform 및 take
- catch와 onCompletion: Flow의 오류 처리
- combine과 zip: 여러 Flow 병합하기
- flowOn과 buffer: 컨텍스트와 백프레셔