Kotlin 코루틴 심화에서는 Flow, Channel, CoroutineScope, 구조화된 동시성 등 실무에서 자주 쓰이는 고급 패턴을 다룬다.
Flow: 비동기 스트림
kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numberFlow(): Flow<Int> = flow {
for (i in 1..5) {
delay(100)
emit(i) // 데이터 방출
}
}
fun main() = runBlocking {
numberFlow()
.filter { it % 2 == 0 }
.map { it * it }
.collect { println(it) } // 4, 16
}
StateFlow / SharedFlow
kotlin
class ViewModel {
private val _state = MutableStateFlow(0)
val state: StateFlow<Int> = _state.asStateFlow()
fun increment() { _state.value++ }
}
// SharedFlow: 이벤트 (replaying)
val events = MutableSharedFlow<Event>(replay = 0)
events.emit(Event.Click)
// 구독
events.collect { handleEvent(it) }
Channel
kotlin
val channel = Channel<Int>(capacity = 10)
// 생산자
launch {
for (i in 1..5) {
channel.send(i)
}
channel.close()
}
// 소비자
launch {
for (item in channel) {
println(item)
}
}
구조화된 동시성
kotlin
suspend fun loadData() = coroutineScope {
val a = async { fetchUser() } // 병렬
val b = async { fetchPosts() } // 병렬
Pair(a.await(), b.await()) // 모두 완료 대기
}
// supervisorScope: 자식 실패가 형제에게 전파 안 됨
supervisorScope {
val job1 = launch { riskyTask1() }
val job2 = launch { riskyTask2() }
}
CoroutineContext와 Dispatchers
kotlin
launch(Dispatchers.IO) { /* I/O 집약적 */ }
launch(Dispatchers.Default) { /* CPU 집약적 */ }
launch(Dispatchers.Main) { /* UI 업데이트 */ }
// 컨텍스트 결합
launch(Dispatchers.IO + CoroutineName("fetcher") + job) { ... }
// withContext: 코루틴 내 컨텍스트 전환
suspend fun fetchAndUpdate() {
val data = withContext(Dispatchers.IO) { fetch() }
withContext(Dispatchers.Main) { updateUI(data) }
}
관련 개념