SupervisorJob과 Job 비교: 실패 격리
SupervisorJob을 사용해 한 자식의 실패가 형제 코루틴을 취소하지 않도록 해 보세요.
SupervisorJob과 Job 비교: 실패 격리은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
기본 Job 실패 전파
일반적인 Job에서는 자식의 실패가 부모를 취소하고, 부모가 모든 형제 코루틴을 취소합니다. 하나의 실패가 전체 계층을 중단시킵니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope {
launch { delay(50); throw RuntimeException("child 1 failed") }
launch { delay(1000); println("child 2 — never prints") }
}
} catch (e: RuntimeException) {
println("Caught: ${e.message}")
}
}SupervisorJob 개요
SupervisorJob은 규칙을 바꿉니다. 자식의 실패는 형제 코루틴이나 부모를 취소하지 않습니다(NOT). 각 자식은 독립적으로 실패합니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val supervisor = SupervisorJob()
val scope = CoroutineScope(coroutineContext + supervisor)
scope.launch { throw RuntimeException("child 1 failed") }
scope.launch { delay(100); println("child 2 still runs") }
delay(200)
supervisor.cancel()
}supervisorScope 빌더
supervisorScope { }는 부모로 SupervisorJob을 사용하는 범위를 생성합니다. 독립적인 자식 코루틴을 실행하는 관용적인 방법입니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
val job1 = launch {
throw RuntimeException("job1 failed")
}
val job2 = launch {
delay(100)
println("job2 succeeded")
}
job1.join() // wait for job1 (it failed)
job2.join() // job2 is unaffected
}
}자식 실패 처리하기
supervisorScope에서는 각 자식이 자체 예외를 처리합니다. 자식에서 처리되지 않은 예외는 각 자식별로 잡아야 합니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
val result = async {
delay(50)
throw RuntimeException("async failed")
}
try {
result.await()
} catch (e: RuntimeException) {
println("Caught from async: ${e.message}")
}
println("Scope continues")
}
}범위 생성 시 Job과 SupervisorJob 비교
개별 자식의 실패 이후에도 유지되어야 하는 서비스나 ViewModel용 CoroutineScope를 생성할 때 SupervisorJob()을 전달합니다.
import kotlinx.coroutines.*
class MyService {
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
fun startTask(name: String) {
scope.launch {
if (name == "fail") throw RuntimeException("$name failed")
println("$name done")
}
}
fun stop() = scope.cancel()
}
fun main() = runBlocking {
val svc = MyService()
svc.startTask("fail")
svc.startTask("ok")
delay(100)
svc.stop()
}viewModelScope는 SupervisorJob을 사용합니다
Android의 viewModelScope는 SupervisorJob을 기반으로 합니다. 하나의 launch가 실패해도 ViewModel의 다른 코루틴은 취소되지 않습니다.
import kotlinx.coroutines.*
// Android ViewModel internals:
// val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
// Each launch is independent — one failure doesn't crash the ViewModel
fun main() = runBlocking {
println("viewModelScope = SupervisorJob + Main")
}supervisorScope를 사용한 병렬 분해
일부 작업이 실패하더라도 서로 영향을 주지 않아야 하는 병렬 작업에는 supervisorScope + async를 사용합니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val results = supervisorScope {
val a = async { delay(50); "result-A" }
val b = async { throw RuntimeException("B failed") }
val c = async { delay(30); "result-C" }
listOf(
runCatching { a.await() },
runCatching { b.await() },
runCatching { c.await() }
)
}
results.forEach { println(it) }
}일반 작업을 사용할 때
모든 자식 작업이 함께 성공해야 할 때는 일반 Job (coroutineScope)을 사용합니다. 하나가 실패하면 그룹 전체를 중단해야 합니다. 트랜잭션처럼 전부 성공하거나 전부 실패하는 방식입니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope { // regular Job
val a = async { delay(50); "A" }
val b = async { throw RuntimeException("B failed") }
println(a.await())
println(b.await()) // throws — cancels a too
}
} catch (e: RuntimeException) {
println("Transaction failed: ${e.message}")
}
}supervisorScope에서의 예외 전파
supervisorScope에서는 자식 작업의 최상위 수준에서 예외가 빠져나갈 때만 범위로 예외가 전파됩니다. 즉, 자식 작업에 try-catch가 없어야 합니다. 부모는 이 예외를 전달받지 않습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
// Exception caught inside child — scope unaffected
launch {
try { throw RuntimeException("handled") }
catch (e: Exception) { println("Child caught: ${e.message}") }
}
delay(100)
println("Scope survived")
}
}SupervisorJob과 CoroutineExceptionHandler
감독자 범위에 CoroutineExceptionHandler를 설치하면 처리되지 않은 자식 작업의 실패를 범위 전체를 중단하지 않고 기록하거나 대응할 수 있습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + handler)
scope.launch { throw RuntimeException("unhandled failure") }
scope.launch { delay(100); println("still running") }
delay(200)
scope.cancel()
}실패 격리 요약
작업: 자식 하나가 실패하면 모두 실패합니다. SupervisorJob: 자식 작업들이 서로 독립적으로 실패합니다. 서비스와 ViewModels에는 감독자를 사용하고, 트랜잭션 그룹에는 일반 작업을 사용합니다.
import kotlinx.coroutines.*
// Decision table:
// coroutineScope { } -> Job: all-or-nothing
// supervisorScope { } -> SupervisorJob: independent failures
// CoroutineScope(SupervisorJob()) -> long-lived service
fun main() = runBlocking { println("Pick the right job for the right scope") }빠른 확인
자식 작업의 실패로 형제 작업이 취소되지 않게 하는 범위는 무엇입니까?
복습
작업: 실패가 형제 작업으로 연쇄됩니다. SupervisorJob/supervisorScope: 실패가 자식 작업별로 격리됩니다. 서로 독립적인 병렬 작업에는 supervisorScope를 사용하고, 트랜잭션 그룹에는 일반 coroutineScope을 사용합니다.
자주 묻는 질문
“SupervisorJob과 Job 비교: 실패 격리” 강의는 무료인가요?
네 — “SupervisorJob과 Job 비교: 실패 격리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“SupervisorJob과 Job 비교: 실패 격리”에서 뭘 배우나요?
SupervisorJob을 사용해 한 자식의 실패가 형제 코루틴을 취소하지 않도록 해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“SupervisorJob과 Job 비교: 실패 격리” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- SupervisorJob과 Job 비교: 실패 격리
- CoroutineExceptionHandler: 전역 미처리 예외 처리기
- async/await 예외 전파
- 복원력 있는 코루틴 아키텍처 설계