catch와 onCompletion: Flow의 오류 처리
상위 Flow의 예외를 포착하고 Flow 완료 이벤트에 반응해 보세요.
catch와 onCompletion: Flow의 오류 처리은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
플로 예외 기초
플로에서 예외가 발생하면 플로가 종료됩니다. 처리하지 않으면 예외가 수집기로 전파되고 플로가 끝납니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("stream error")
emit(2)
}.collect { println(it) }
} catch (e: Exception) {
println("Caught: ${e.message}")
}
}예외 처리 연산자
catch는 상위 흐름의 예외를 처리하며 대체 값을 내보내거나 예외를 다시 던질 수 있습니다. 수집기 자체에서 발생한 예외는 처리하지 않습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit(1)
throw RuntimeException("oops")
}.catch { e ->
println("Caught: ${e.message}")
emit(-1) // fallback value
}.collect { println(it) } // 1, then -1
}예외 포착은 상위 흐름만 처리합니다
catch는 플로 빌더와 상위 연산자에서 발생한 예외만 가로챕니다. collect 람다에서 발생한 예외는 가로채지 않습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flowOf(1, 2, 3)
.catch { e -> println("upstream: ${e.message}") }
.collect {
if (it == 2) throw RuntimeException("collector error") // not caught by catch
println(it)
}
} catch (e: Exception) {
println("Collector exception: ${e.message}")
}
}예외 처리 중 다시 던지기
예외를 검사한 후 처리할 수 없는 예외만 선택적으로 다시 던질 수 있습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw IllegalStateException("state error")
}.catch { e ->
if (e is RuntimeException) { emit(-1); return@catch }
throw e // rethrow unknown exceptions
}.collect { println(it) }
} catch (e: Exception) {
println("Rethrown: ${e.message}")
}
}onCompletion 연산자
onCompletion은 플로가 정상적으로 또는 예외와 함께 완료될 때 실행됩니다. 실패하면 cause 매개변수에 예외가 전달됩니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf(1, 2, 3)
.onCompletion { cause ->
if (cause == null) println("Completed normally")
else println("Failed: ${cause.message}")
}
.collect { println(it) }
}오류 발생 시 onCompletion
상위 흐름에서 예외가 발생해도 onCompletion은 실행됩니다. 예외를 cause로 받지만 억제하지 않으므로 예외는 계속 전파됩니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("error")
}.onCompletion { cause ->
println("onCompletion cause=${cause?.message}")
}.collect { println(it) }
} catch (e: Exception) {
println("outer catch: ${e.message}")
}
}catch와 onCompletion 결합하기
catch로 복구하고 대체 값을 내보낸 다음, onCompletion으로 결과와 관계없이 로그를 기록하거나 리소스를 해제하십시오.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit("ok")
throw RuntimeException("network error")
}.catch { e ->
emit("fallback") // recover
}.onCompletion {
println("Stream done — release resources")
}.collect { println(it) }
}retry 연산자
retry(n) { ... }는 예외가 발생하면 최대 n번까지 상위 플로를 다시 구독합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
var attempt = 0
fun unstableFlow() = flow {
attempt++
if (attempt < 3) throw RuntimeException("attempt $attempt failed")
emit("success on attempt $attempt")
}
fun main() = runBlocking {
unstableFlow()
.retry(3) { e -> println("retrying: ${e.message}"); true }
.collect { println(it) }
}사용자 지정 로직을 위한 retryWhen
retryWhen은 예외와 시도 횟수를 제공하므로, 백오프를 추가하거나 재시도를 발생시킬 예외를 필터링할 수 있습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
var n = 0
flow {
if (n++ < 2) throw IOException("IO error")
emit("done")
}.retryWhen { cause, attempt ->
cause is IOException && attempt < 3
}.collect { println(it) }
}onStart 연산자
onStart는 첫 번째 값이 방출되기 전에 실행되므로 데이터가 도착하기 전에 로드 중 상태를 표시하거나 리소스를 초기화할 때 유용합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf("data")
.onStart { emit("Loading...") }
.onCompletion { emit("Done") }
.collect { println(it) }
}실제 응용 프로그래밍 인터페이스 호출에서의 Error 처리
저장소 플로우를 catch로 감싸 예외를 도메인 오류로 매핑하고, onCompletion으로 로딩 표시기를 숨기십시오.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
sealed class State { object Loading : State(); data class Data(val v: String) : State(); data class Error(val msg: String) : State() }
fun apiFlow(): Flow<String> = flow { delay(50); emit("response") }
fun uiFlow(): Flow<State> = apiFlow()
.map { State.Data(it) as State }
.onStart { emit(State.Loading) }
.catch { e -> emit(State.Error(e.message ?: "unknown")) }
fun main() = runBlocking { uiFlow().collect { println(it) } }빠른 확인
catch 연산자의 핵심적인 한계는 무엇입니까?
복습
catch 연산자는 상류 예외를 처리하고 대체 값을 방출할 수 있습니다. onCompletion은 정상 완료든 오류든 항상 실행되어 정리 또는 로그 기록에 사용됩니다. 복원력 있는 플로우 파이프라인을 만들려면 재시도/retryWhen과 함께 사용하십시오.
AI 튜터와 함께 Kotlin을(를) 배우세요 — 무료
브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.
- 코스
- 51
- 레슨
- 203
자주 묻는 질문
“catch와 onCompletion: Flow의 오류 처리” 강의는 무료인가요?
네 — “catch와 onCompletion: Flow의 오류 처리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“catch와 onCompletion: Flow의 오류 처리”에서 뭘 배우나요?
상위 Flow의 예외를 포착하고 Flow 완료 이벤트에 반응해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“catch와 onCompletion: Flow의 오류 처리” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Flow 연산자: map, filter, transform 및 take
- catch와 onCompletion: Flow의 오류 처리
- combine과 zip: 여러 Flow 병합하기
- flowOn과 buffer: 컨텍스트와 백프레셔