CoroutineExceptionHandler: 전역 미처리 예외 처리기
CoroutineExceptionHandler를 설치해 처리되지 않은 예외를 기록하거나 복구해 보세요.
CoroutineExceptionHandler: 전역 미처리 예외 처리기은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
CoroutineExceptionHandler란 무엇입니까?
CoroutineExceptionHandler는 catch 처리기가 없는 코루틴에서 처리되지 않은 예외를 처리하는 컨텍스트 요소입니다. 최후의 수단으로 작동합니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { context, exception ->
println("Caught unhandled: ${exception.message}")
}
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default + handler)
scope.launch { throw RuntimeException("oops") }
delay(100)
}루트 코루틴에만 사용
CoroutineExceptionHandler는 루트 코루틴, 즉 범위에서 직접 시작된 코루틴의 예외만 포착합니다. 자식 코루틴의 예외는 처리기로 가지 않고 부모로 전파됩니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Root coroutine — handler fires:
CoroutineScope(handler).launch {
throw RuntimeException("root error")
}
delay(100)
// NOT handler (child of coroutineScope):
// launch { launch { throw RuntimeException() } }
}예외를 억제하지 않음
처리기는 예외로 인해 코루틴이 이미 취소된 후에 호출됩니다. 처리기는 기록, 충돌 보고 또는 정리를 위한 것이며 실행을 재개하기 위한 것이 아닙니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e ->
println("[CrashReport] ${e::class.simpleName}: ${e.message}")
// send to Crashlytics, Sentry, etc.
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).apply {
launch { throw IllegalStateException("state error") }
launch { delay(100); println("still alive") }
delay(200)
cancel()
}
}처리기 + SupervisorJob
SupervisorJob + CoroutineExceptionHandler 조합은 오래 유지되는 범위에 사용하는 표준 패턴입니다. 자식 작업은 독립적으로 실패하고, 처리되지 않은 실패는 기록됩니다.
import kotlinx.coroutines.*
class AppScope {
private val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
}
fun main() = runBlocking {
val app = AppScope()
app.scope.launch { throw RuntimeException("task failed") }
app.scope.launch { delay(100); println("other task ok") }
delay(200)
app.scope.cancel()
}async와 처리기
async에서는 예외가 Deferred에 저장되고 await()에서 발생합니다. deferred를 기다리지 않은 경우가 아니라면 async에서는 처리기가 호출되지 않습니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob() + handler)
val deferred = scope.async { throw RuntimeException("async error") }
try {
deferred.await() // exception thrown here
} catch (e: RuntimeException) {
println("Caught from await: ${e.message}")
}
delay(50)
scope.cancel()
}Thread.UncaughtExceptionHandler 비교
Java의 UncaughtExceptionHandler와 달리 Kotlin의 처리기는 코루틴 컨텍스트의 일부이며 해당 범위의 코루틴 안에서만 적용됩니다.
import kotlinx.coroutines.*
// Java style (applies to threads):
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("Thread ${t.name} threw: ${e.message}")
}
// Kotlin coroutine style (applies to coroutines in scope):
val handler = CoroutineExceptionHandler { _, e ->
println("Coroutine threw: ${e.message}")
}
fun main() = runBlocking { println("Handlers target different concurrency models") }MDC를 사용한 기록 패턴
서버 앱에서는 처리기가 요청 ID와 같은 코루틴 컨텍스트 정보를 수집하여 구조화된 기록에 사용할 수 있습니다. 그런 다음 기록 프레임워크로 전달합니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { ctx, e ->
val jobName = ctx[CoroutineName]?.name ?: "unknown"
println("[${jobName}] ERROR: ${e.message}")
}
fun main() = runBlocking {
CoroutineScope(SupervisorJob() + handler).launch(CoroutineName("DataLoader")) {
throw RuntimeException("fetch failed")
}
delay(100)
}충돌 보고 통합
처리기를 사용하여 처리되지 않은 예외를 Firebase Crashlytics나 Sentry 같은 충돌 보고 서비스로 전달합니다.
import kotlinx.coroutines.*
object CrashReporter {
fun record(e: Throwable) = println("[Crashlytics] ${e.message}")
}
val handler = CoroutineExceptionHandler { _, e ->
if (e !is CancellationException) CrashReporter.record(e)
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
fun main() = runBlocking {
appScope.launch { throw RuntimeException("unhandled in production") }
delay(100)
appScope.cancel()
}처리기 상속
부모 컨텍스트의 처리기는 자식 코루틴에 자동으로 상속되지 않습니다. 처리기가 호출되려면 루트 코루틴의 컨텍스트에 처리기가 있어야 합니다.
import kotlinx.coroutines.*
val handler = CoroutineExceptionHandler { _, e -> println("Handler: ${e.message}") }
fun main() = runBlocking {
// Handler only fires at root level:
CoroutineScope(SupervisorJob() + handler).launch {
// Child of root — exception propagates to root handler:
launch { throw RuntimeException("nested") }
}
delay(100)
}모범 사례 요약
앱 수준 또는 기능 수준 범위에는 항상 CoroutineExceptionHandler를 설치합니다. 취소로 인한 예외가 아닌 모든 예외를 기록합니다. 처리기를 제어 흐름에 사용해서는 안 됩니다. 처리기는 관찰 가능성을 위한 기능일 뿐입니다.
import kotlinx.coroutines.*
val globalHandler = CoroutineExceptionHandler { ctx, e ->
if (e !is CancellationException) {
println("[ERROR] ${ctx[CoroutineName]?.name}: ${e.message}")
}
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + globalHandler)
fun main() = runBlocking {
appScope.launch(CoroutineName("Auth")) { throw RuntimeException("token expired") }
delay(100); appScope.cancel()
}빠른 확인
CoroutineExceptionHandler가 자동으로 호출되지 않는 코루틴 유형은 무엇입니까?
복습
CoroutineExceptionHandler는 루트 코루틴의 처리되지 않은 예외를 관찰하는 최후의 수단입니다. 오래 유지되는 범위에는 SupervisorJob과 함께 사용합니다. 기록과 충돌 보고에 사용하고, 제어 흐름에는 사용하지 않습니다.
자주 묻는 질문
“CoroutineExceptionHandler: 전역 미처리 예외 처리기” 강의는 무료인가요?
네 — “CoroutineExceptionHandler: 전역 미처리 예외 처리기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“CoroutineExceptionHandler: 전역 미처리 예외 처리기”에서 뭘 배우나요?
CoroutineExceptionHandler를 설치해 처리되지 않은 예외를 기록하거나 복구해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“CoroutineExceptionHandler: 전역 미처리 예외 처리기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- SupervisorJob과 Job 비교: 실패 격리
- CoroutineExceptionHandler: 전역 미처리 예외 처리기
- async/await 예외 전파
- 복원력 있는 코루틴 아키텍처 설계