(π¨ μ€λ₯ μ μ ) π€ 2025λ λμλ κ°λ°μλ€μ μ½λ£¨ν΄ μμΈ μ²λ¦¬ λλ¬Έμ λ°€μκ°? π¨ (2025νλ λ μλλ‘μ΄λ νꡬμμ λ¬Έμ νμ΄)
κ°μΈ κ΄κ³ μμ
μ΄ κΈμ 2025 μλλ‘μ΄λ νꡬ μμμ λμ¨ λ¬Έμ μ€ μΌλΆλ₯Ό ν΄μνλ κΈμ ννλ‘ μμ±ν©λλ€. λ¬Έμ μ 체λ₯Ό λ΄μ§ μκ³ , μ€μν ν΄μ€μ μμ±ν©λλ€.
μ μ
24.12.11 ν΄μμ μ€λ₯κ° μμΌλ©°, μ½λ κ²μ¦ κ³Όμ μμ μ€λ₯λ₯Ό νμΈνμ¬ μμ ν©λλ€.
λκΈλ‘ μ€λ₯κ° μλ€κ³ μλ €μ£Όμ Larry, μ‘μ€μλ κ°μ¬ν©λλ€.
μλλ‘μ΄λ νꡬ μμ νκΈ° κΈ
- 2025νλ λ μλλ‘μ΄λ νꡬμμ - link
- 2025νλ λ μλλ‘μ΄λ νꡬμμμ μ€λΉνλ©°(κ²½μλ μμ±) - link
μ΄λ€ λ¬Έμ μΌκΉ?
μ½λ£¨ν΄ Exception λ°μ μ μμΈ λ²μλ₯Ό λ¬Όμ΄λ³΄λ μ§λ¬Έμ λν ν΄μμ λ΄λ κΈμ΄λ€.
λλ΅ μ μ΄λ³΄λ©΄
- μ΅μμ Job Aλ viewModelScope.launchλ‘ μμ±λκ³ λ΄λΆμμ B, Cλ₯Ό μμ±νλ€.
- Bμμλ coroutineScope λ΄μμ D, Eλ₯Ό μμ±νλ€.
- Cμμλ withContext(Dispatchers.IO) λ΄μμ Fλ₯Ό μμ±νλ€.
λͺ¨λ Jobμ΄ Finish λμλ€κ³ κ°μ
A-FκΉμ§ λͺ¨λ Jobμ΄ λ¦¬ν΄λλ€λ μ¬μ€κ³Ό λͺ¨λ Jobμ΄ λμ μλ£λμμ λλ₯Ό κ°μ νλ€.
μ΄ λΆλΆμ λν κΈμ μ΄λ―Έ κ³Όκ±°μλ μμ±νμ΄μ λ§ν¬λ₯Ό μΆκ°ν΄λκ² λ€.
μ΄ λ κ°μ κΈμ μ΄ν΄νλ€λ©΄ μ¬μ€ ν΄μν νμλ μμ§λ§, μλ‘μ΄ λ§μμΌλ‘ κΈμ μ μ΄λ³Έλ€.
μ΄ κΈμμλ
- 2025 μλλ‘μ΄λ νꡬ μμμ λμ¨ λ¬Έμ μΌλΆλ₯Ό μ 리νλ€.
- Jobμ λν μ΄ν΄κ° νμνλ€.
λ¬Έμ μ ν΄μ
λͺ¨λ μ€νμμ Jobμ κ°μ§λ €λ©΄ launch {}
λ₯Ό ν΅ν΄ μλ‘μ΄ μμ
μ μ€νν΄μΌ νλ€λ μ μ΄λ€.
async
λ DeffDeferred Tλ₯Ό 리ν΄νκΈ°μ μ μ νμ§ μμ μ€νμ ν΄λΉνκΈ°μ μ½λλ‘ μμ±νλ©΄ μλμ κ°λ€.
// Aμ μ€ν
viewModelScope.launch {
// Bμ μ€ν
launch {
coroutineScope {
// Dμ μ€ν
launch { }
// Eμ μ€ν
launch { }
}
}
// Cμ μ€ν
launch {
withContext(Dispatchers.IO) {
// Fμ μ€ν
launch { }
}
}
}
μ΄ λ¬Έμ λ₯Ό ν΄μν λ μ£Όμν μ μ΄ νλ μλ€.
Coroutine builderλ‘ μ€ννλ κ²½μ° λΆλͺ¨μ CoroutineContextλ νμ(μμ) λͺ¨λ μμλ°λ κ²μ΄ μλλΌλ μ μ΄λ€. μ½λλ₯Ό μΆμ νλ©΄ foldλ₯Ό ν΅ν΄ ν©μ°νλ€.
λ¨, Jobμ μμλ°μ§ μλλ° λ€μκ³Ό κ°μ μ΄μ λ‘ μ λ―Έλμ΄μ μ€λͺ μ΄λ€.
λ§μ½ Jobμ΄ μμλλ€λ©΄, λΆλͺ¨ μ½λ£¨ν΄μ Jobμ΄ μ·¨μλ λ μμ μ½λ£¨ν΄λ ν¨κ» μ·¨μλ©λλ€. μ΄λ κ° μ½λ£¨ν΄μ μλͺ μ£ΌκΈ°λ₯Ό κ°λ³μ μΌλ‘ κ΄λ¦¬νκΈ° μ΄λ ΅κ² λ§λλλ€. κ° μ½λ£¨ν΄μ΄ λ 립μ μΈ Jobμ κ°μ§λλ‘ ν¨μΌλ‘μ¨, μ½λ£¨ν΄μ μ·¨μμ μλͺ μ£ΌκΈ° κ΄λ¦¬λ₯Ό λμ± μ μ°νκ² μ μ΄ν μ μμ΅λλ€.
κ²°κ΅ νμν κ²λ§ ν©μ°νκ³ μΉνν μ μμΌλ©°, Jobμ μμΈλ‘ μμλ°μ§ μλλ€.
ν¨μ λ μ°Ύμ보μ.
μ΄ λ¬Έμ μλ 2κ°μ§ ν¨μ μ΄ μλ€. λ°λ‘ coroutineScope
κ³Ό withContext(Dispatchers.IO)
μ΄λ€.
μ΄ μ½λμμλ μ¬μ€ μλ¬΄λ° μλ―Έκ° μλ€. μ΄μ°¨νΌ launch {}
λ₯Ό ν΅ν΄ μ½λλ₯Ό μ€ννκΈ° λλ¬Έμ blocking
μ λ§λλ coroutineScope
κ³Ό withContext(Dispatchers.IO)
μ½λμ μ¬μ©μ μλ―Έκ° μκ³ ν¨μ μ λ§λ€κΈ° μν μ½λ μ€λͺ
μ΄λΌλ μ μ΄λ€.
Job?
Jobμλ ν¬κ² 2κ° μλ€.
κ·Έλ₯ Job - linkκ³Ό SupervisorJob - linkμ κ°μ§λ€.
μ΄ λμ λ± νλμ μ°¨μ΄κ° μλλ°, νμ Jobμμ λ°μνλ Exception μΌμ΄μ€λ‘ μΈν΄ λΆλͺ¨κ° μν₯μ λ°λκ° μλκ°μ΄λ€.
μ΄μ κΈμμλ μμ±νμ§λ§ Kotlin Coroutines Exception μν₯λ μμ보기λ₯Ό μ€μ΄κΈ° μν΄μλ SupervisorJobμ νμ©νλ κ²μ΄ μ ν©νλ€.
λ€νν android viewModelScopeμ SupervisorJob
μ κΈ°λ³ΈμΌλ‘ νμ©νκ³ μλ€.
Jobμ λΌμ΄ν μ¬μ΄ν΄λ κ°μ§κ³ μλλ° μλμ κ·Έλ¦Όκ³Ό κ°λ€.
μ΄ λΆλΆμ κΌ κΈ°μ΅ν μ΄μ λ μμ§λ§ cancel/fail
μ²λ¦¬ μ Cancelled
μνλ‘ λ³κ²½λλ€λ μ μ΄ μ€μν λΆλΆμ΄λ€.
μ΄κ±Έ μμ§ μλλΌλ μ½λ£¨ν΄μμλ exception λ°μ μ runCatch
λ§ μ κ±Έμ΄λ λ¬Έμ κ° μμΌλ©°, μ€λ₯κ° λ°μνλλΌλ μ¬μλ κ°λ₯νλ€λ μ μ΄ μ€μν ν¬μΈνΈ μλκΉ μΆλ€.
λ¬Έμ ν΄μ μ μ .
μ λ΄μ©μΌλ‘ μ μ μλ μ¬μ€μ κ·Έλμ μν₯λκ° μ΄λκΉμ§ μ νλ κΉμ΄λ€.
// Aμ μ€ν
viewModelScope.launch {
// Bμ μ€ν
launch {
coroutineScope {
// Dμ μ€ν
launch { }
// Eμ μ€ν
launch { }
}
}
// Cμ μ€ν
launch {
withContext(Dispatchers.IO) {
// Fμ μ€ν
launch { }
}
}
}
μ΄ μ½λλ μ΄λμμ μ€λ₯κ° λλ viewModelScope.launch {}μΈ Aκ° μ’ λ£λλ€.
κ·Έλ κΈ°μ λ¬Έμ μ λμ¨ λ΅λ³μ μ λ΅μ΄ μμ μ μλ€.
κ·Έλλ κΆκΈνμμ
κ·ΈλΌ μ μ½λμμ μΌλΆμ μμ μ Job()λ‘ λ€μ λ³κ²½νλ©΄ μν₯μ μ΄λ»κ² λ¬λΌμ§κΉ?
μμ μ μλ μ½λμ Bμ μμ
μ Job()
μΌλ‘ μΉννλ©΄ μ΄λ€ μΌμ΄ λ²μ΄μ§κΉ?
// Aμ μ€ν
CoroutinesScope(SupervisorJob()).launch {
// Bμ μ€ν
launch(Job()) { // JobμΌλ‘ λ³κ²½
// Dμ μ€ν
launch { throw Exception("exception") }
// Eμ μ€ν
launch { }
}
// Cμ μ€ν
launch {
// Fμ μ€ν
launch { }
}
}
κ°λ¨νλ€.
- Aλ ꡬ쑰νκ° κΉ¨μ§ Bμ μν₯μ λ°μ§ μμΌλ©°, C λ΄λΆμμ λ°μν μ€λ₯ μμ μν₯λ°μ§ μλλ€.
- Bλ μλ‘μ΄ Jobμ μμ±νμκΈ°μ Aμ 무κ΄νλ©° D/Eμ μμ μ€ν¨μ λν μν₯ λ°λλ€.
- Cλ Fμμ λ°μνλ μ€λ₯μ μν₯λ°μ§ μλλ€.
- Cλ μλ‘μ΄ Jobμ μμ±ν Bμμ λ°μν μ€λ₯μ λν μν₯ λ°μ§ μλλ€.
μ΄λ° μ΄μ λ μ λ―Έλμ΄μμ μ€λͺ ν Jobμ μμΈ μ€λͺ μμ μΆ©λΆν μ λμ¨λ€.
Job λμ μ¬μ©ν μ μλ μμ ν λ°©λ²μ
supervisorScope
μ μ¬μ©νλ λ°©λ²μ΄ μμΌλ μ°Έκ³ νμ¬ μ¬μ©νμκΈΈ
// Aμ μ€ν
CoroutinesScope(SupervisorJob()).launch {
// Bμ μ€ν
supervisorScope {
launch { // JobμΌλ‘ λ³κ²½
// Dμ μ€ν
launch { throw Exception("exception") }
// Eμ μ€ν
launch { }
}
}
// Cμ μ€ν
launch {
// Fμ μ€ν
launch { }
}
}
κ°λ¨ν μ리 μ μ ν¬ν¨
λ΄λΆ μ½λλ 무κ΄νκ² μλμ κ°λ€.
val a = viewModelScope.launch {
// μ¬κΈ°μ μ€λ₯κ° λκ±°λ
}
val b = viewModelScope.launch {
// μ¬κΈ°μ μ€λ₯κ° λκ±°λ
}
μμ κ°μ΄ a/bμ μ΅μμ viewModelScopeμ λν launch {}λ₯Ό μ€νν λλ a/b μ€ μ΄λ κ³³μμ exceptionμ΄ λ°μνλλΌλ μλ‘ μν₯ λ°μ§ μλλ€.
μ΄μ μ μ€λ₯λ₯Ό λ²ν μ΄μ λ μλμ κ°μ λ΄λΆ μ½λλ₯Ό μ°Έκ³ νμκΈ° λλ¬Έμ΄λ€.
λΉμ°νκ²λ launchμ μμ viewModelScope.launch {}λ₯Ό λΆλͺ¨λ‘ κ°μ§κ³ μμμκ±°λΌκ³ μ°©κ°ν λΆλΆμ΄λ€.
private class SupervisorJobImpl(parent: Job?) : JobImpl(parent) {
override fun childCancelled(cause: Throwable): Boolean = false
}
μ§κΈ νμ¬μ Jobκ³Ό Parent Jobμ λͺ¨λ κ°μ§κ³ μν΅νλ€λ μ μ μ μ μλ€.
private val _parentHandle = atomic<ChildHandle?>(null)
internal var parentHandle: ChildHandle?
get() = _parentHandle.value
set(value) { _parentHandle.value = value }
override val parent: Job?
get() = parentHandle?.parent
λ§λ¬΄λ¦¬
κ°λ¨νκ² 2025 μλλ‘μ΄λ νꡬμμμ Exception μ νμ λν΄ μ 리νμλ€.
μ΄ λ¬Έμ λ₯Ό μ μ μλ κ²μ
- Jobμ
cancel/fail
λ°μ μ νμ¬ μνλ₯ΌCancelled
μ²λ¦¬νλ€. - Jobμ νμ contextμ μ λ¬λμ§ μμ§λ§ Parent.jobμ νμ Jobμμλ λ³λλ‘ κ΄λ¦¬νλ€.
- SupervisorJobκ³Ό Jobμ μ€κ°μ νΌμ©ν΄μ μ¬μ©νλ κ²½μ°μλ Job λΆλΆμ λͺ¨λ μ’ λ£ μ²λ¦¬νλ€.
- launchλ‘ μ€νν κ²½μ° return κ²°κ³Όλ Jobμ΄ λλ€.
Jobκ³Ό SupervisorJobμ μ€μμ±μ μ΄ν΄ν μ μλ κ°λ¨ν λ¬Έμ μ λλ€.
μ μ νλ©΄μ
AIμκ² μ§λ¬Έμ λ€ λ¨κ²¨λ³΄μλλ° μλ‘ λ€λ₯Έ λ΅λ³μ μ€λ€.
AIμ μλ΅μ΄ 100% λ΅μ μλκ² μ§λ§ μΌλΆ λ§λ€κ³ κ°μ νκ³ μ΄μΌκΈ°νκ³ , λ΄κ° μκ³ μλ λ΄μ©μ μ λ¬νλ©΄μ μ€λ₯κ° μκ²Όλ€. μ λΉν μλ°νκ² μ¬μ©νλ©΄ μ μ©ν λꡬμμ λ§λ€.
κ²°κ΅ μ½λ κ²μ¦μ ν΅ν΄ μλͺ»λμλ€λ κ±Έ λ°κ²¬νκ³ λμ μμ μ νμ§λ§ μ¬λ―Έμλ λ¬Έμ μμ λ§λ€.
μ€μ κ°λ°ν λλ μ΄λ κ² μ¬μ©νλλΌλ runCatch
λ₯Ό νμ λ¬κ³ μ¬μ©νλ ν¬κ² λ¬Έμ λ₯Ό λλΌμ§ λͺ»νμλ€.
μ½λ£¨ν΄ μμΈ μ νμ λν μμ μΆκ°
μ°ν μ½ ν¬λ£¨ μ€λ₯μ΄λμ μ½λ£¨ν΄ μμΈ μ²λ¦¬ μμμ μΆκ°ν©λλ€.
Comments