Kotlin Academy · 강의

catch와 onCompletion: Flow의 오류 처리

상위 Flow의 예외를 포착하고 Flow 완료 이벤트에 반응해 보세요.

레슨 2/413개 단계

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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Flow 연산자: map, filter, transform 및 take
  2. catch와 onCompletion: Flow의 오류 처리
  3. combine과 zip: 여러 Flow 병합하기
  4. flowOn과 buffer: 컨텍스트와 백프레셔
← Kotlin Academy(으)로 돌아가기