finally와 NonCancellable로 정리하기
finally와 withContext(NonCancellable)를 사용해 취소된 코루틴에서 리소스를 해제해 보세요.
finally와 NonCancellable로 정리하기은(는) CoddyKit의 무료 Kotlin Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Kotlin Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
취소와 정리 블록
코루틴이 취소되면 일시 중단 지점에서 CancellationException이 발생합니다. finally 블록의 코드는 항상 실행되지만, finally 자체는 이미 취소된 코루틴 컨텍스트에서 실행됩니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} finally {
println("finally: cleaning up")
}
}
delay(50)
job.cancel()
job.join()
}문제: 정리 블록에서 일시 중단하기
취소된 코루틴의 finally 안에서 delay 또는 다른 일시 중단을 시도하면 컨텍스트가 이미 취소된 상태이므로 즉시 예외가 발생합니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} finally {
// delay(100) // throws CancellationException here!
println("Sync cleanup OK; async cleanup needs NonCancellable")
}
}
delay(50); job.cancel(); job.join()
}withContext(NonCancellable)
finally 안의 일시 중단 호출을 withContext(NonCancellable)로 감싸면 부모가 취소된 후에도 취소할 수 없는 컨텍스트에서 실행할 수 있습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} finally {
withContext(NonCancellable) {
delay(100) // OK: runs despite cancellation
println("Async cleanup complete")
}
}
}
delay(50); job.cancel(); job.join()
}NonCancellable을 사용하는 경우
데이터베이스 연결 닫기, 로그 플러시, 분석 이벤트 전송 또는 취소와 관계없이 완료되어야 하는 모든 비동기 정리 작업에는 NonCancellable을 사용하십시오.
import kotlinx.coroutines.*
suspend fun closeConnection() {
println("Closing DB connection...")
delay(50) // simulate async close
println("Connection closed")
}
fun main() = runBlocking {
val job = launch {
try { delay(1000) }
finally { withContext(NonCancellable) { closeConnection() } }
}
delay(50); job.cancel(); job.join()
}NonCancellable은 범위가 아닙니다
NonCancellable은 withContext에 전달할 수 있는 Job입니다. 이를 코루틴 범위로 직접 사용하지 말고 finally 정리 작업에서만 사용하십시오.
import kotlinx.coroutines.*
fun main() = runBlocking {
// WRONG usage:
// launch(NonCancellable) { ... } // launches a coroutine that cannot be cancelled
// RIGHT usage:
launch {
try { delay(500) }
finally {
withContext(NonCancellable) {
println("Safe cleanup")
}
}
}.also { delay(50); it.cancel(); it.join() }
}여러 리소스 정리하기
여러 정리 작업을 하나의 withContext(NonCancellable) 블록 안에서 연결하십시오.
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
try {
delay(1000)
} finally {
withContext(NonCancellable) {
delay(20); println("Step 1: flush cache")
delay(20); println("Step 2: close socket")
delay(20); println("Step 3: log audit")
}
}
}.also { delay(50); it.cancel(); it.join() }
}예외 처리와 정리 패턴
비즈니스 오류에는 예외 처리를 사용하고 정리에는 정리 블록을 사용하십시오. 이것이 표준 구조화 패턴입니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
try {
delay(100)
throw RuntimeException("business error")
} catch (e: RuntimeException) {
println("Handling: ${e.message}")
} finally {
withContext(NonCancellable) {
println("Always cleanup")
}
}
}.join()
}정리 순서
정리 블록은 중첩된 순서의 반대로 실행됩니다. 바깥쪽 try-finally는 안쪽 블록이 실행된 후 실행되며, 일반적인 Java/코틀린 코드와 같습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
try {
try {
delay(1000)
} finally { println("Inner cleanup") }
} finally { println("Outer cleanup") }
}.also { delay(50); it.cancel(); it.join() }
}AutoCloseable 리소스 자동 정리
AutoCloseable 리소스에는 Kotlin의 use { } 확장 함수를 사용하십시오. 예외나 취소가 발생해도 close()를 자동으로 호출합니다.
import kotlinx.coroutines.*
class Connection : AutoCloseable {
init { println("Opened") }
override fun close() { println("Closed") }
suspend fun query(): String { delay(50); return "result" }
}
fun main() = runBlocking {
val result = Connection().use { it.query() }
println(result)
}취소 이유 기록
catch 또는 finally에서 CancellationException의 취소 메시지를 가져오면 코루틴이 중지된 이유를 기록할 수 있습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
try {
delay(1000)
} catch (e: CancellationException) {
println("Cancelled: ${e.message}")
throw e
}
}
delay(50)
job.cancel("user navigated away")
job.join()
}invokeOnCompletion을 사용한 CoroutineScope 정리
Job.invokeOnCompletion은 작업이 어떤 이유로든 완료될 때 실행되는 콜백을 등록합니다. 부모 수준에서 정리할 때 finally를 대신할 수 있습니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch {
delay(1000)
}
job.invokeOnCompletion { cause ->
if (cause != null) println("Ended with: ${cause::class.simpleName}")
else println("Completed normally")
}
delay(50)
job.cancel()
job.join()
}빠른 확인
finally 블록에서 withContext(NonCancellable)을 사용하는 목적은 무엇인가요?
복습
취소가 발생해도 finally는 항상 실행됩니다. 취소된 후에도 일시 중단 호출이 완료되도록 finally 안에서 해당 호출을 withContext(NonCancellable)로 감싸십시오. AutoCloseable 리소스에는 use { }를 사용하십시오.
자주 묻는 질문
“finally와 NonCancellable로 정리하기” 강의는 무료인가요?
네 — “finally와 NonCancellable로 정리하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Kotlin Academy 강의 전체를 잠금 해제할 수 있습니다. Kotlin Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“finally와 NonCancellable로 정리하기”에서 뭘 배우나요?
finally와 withContext(NonCancellable)를 사용해 취소된 코루틴에서 리소스를 해제해 보세요. 브라우저에서 직접 실행하는 실습 코드로 Kotlin Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Kotlin Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Kotlin Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“finally와 NonCancellable로 정리하기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Kotlin Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Kotlin Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 협력적 취소: isActive와 ensureActive
- withTimeout과 withTimeoutOrNull
- finally와 NonCancellable로 정리하기
- 코루틴 계층 구조에서 취소 전파