0Pricing
Kotlin Academy · 강의

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

이 강의의 모든 강의

  1. 협력적 취소: isActive와 ensureActive
  2. withTimeout과 withTimeoutOrNull
  3. finally와 NonCancellable로 정리하기
  4. 코루틴 계층 구조에서 취소 전파
← Kotlin Academy(으)로 돌아가기