Coroutine 예외 처리 1편 - Exception 전파, CoroutineExceptionHandler 사용해 전파된 예외 처리하기

2023. 5. 11. 13:30·공식 문서 번역/Coroutines 공식 문서
반응형

이 섹션에서는 예외 처리와 예외 발생 시 취소에 대해 다룬다. 우리는 취소된 Coroutine이 일시중단 지점에서 CancellationException을 발생시키고 이것이 Coroutine의 동작원리에 의해서 무시되는 것을 알고 있다. 이 장에서는 취소 도중 예외가 발생되거나 같은 Coroutine에서 복수의 자식 Coroutine이 예외를 발생시킬 경우 어떤 일이 일어나는지 살펴볼 것이다.

 

Exception 전파

Coroutine 빌더는 자동으로 예외를 전파(launch와 actor)하거나 사용자에게 예외를 노출(async와 produce)한다. 이 빌더들이 다른 Coroutine의 자식이 아닌 root Coroutine을 만드는데 사용될 때, 전자(launch와 actor)는 Java의 Thread.uncaughtExceptionHandler와 비슷하게 앞의 빌더들은 예외를 잡히지 않은 예외*1로 다룬다. 반면 후자(async와 produce)는 await이나 recieve를 통해 사용자가 마지막 예외를 소비하는지에 의존한다.

*produce와 receive는 Channel 섹션에서 다룬다

 

이는 GlobalScope를 사용해 root Coroutine을 만드는 간단한 예제로 설명될 수 있다.

 

📖  GlobalScope는 사소하지 않은 역효과를 만들 수 있는 섬세하게 다뤄져야 하는 API이다. 모든 어플리케이션에 대해 root Coroutine을 만드는 것은 GlobalScope의 드문 적합한 사용 방법 중 하나이다. 따라서 @OptIn(DelicateCoroutinesApi::class)을 사용해 GlobalScope를 명시적으로 opt-in*2 시켜야 한다.

 

@OptIn(DelicateCoroutinesApi::class)
fun main() = runBlocking {
    val job = GlobalScope.launch { // root coroutine with launch
        println("Throwing exception from launch")
        throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
    }
    job.join()
    println("Joined failed job")
    val deferred = GlobalScope.async { // root coroutine with async
        println("Throwing exception from async")
        throw ArithmeticException() // Nothing is printed, relying on user to call await
    }
    try {
        deferred.await()
        println("Unreached")
    } catch (e: ArithmeticException) {
        println("Caught ArithmeticException")
    }
}

📌 전체 코드는 이곳에서 확인할 수 있습니다.

 

이 코드의 출력은 다음과 같다(디버그 옵션을 켜놓았음*3) :

Throwing exception from launch
Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.IndexOutOfBoundsException
Joined failed job
Throwing exception from async
Caught ArithmeticException

 

 


📖 아래 내용은 독자의 이해를 위해 번역자가 추가한 글입니다.

*1. uncaught exceptions를 잡히지 않은 예외로 번역했다.

*2. Opt-in 이란 명시적으로 사용을 동의하는 것을 뜻한다. Kotlin 안전하게 사용하기 위해 Opt-in을 요구하는 경우가 많다.

*3. JVM option에 -Dkotlinx.coroutines.debug을 추가하면 Coroutine 디버깅이 가능하다.


이 글은 Coroutines 공식 문서를 번역한 글입니다.

 

원문 : Coroutine exceptions handling - Exception propagation

원문 최종 수정 :  2022년 6월 27일

 


CoroutineExceptionHandler 사용해 전파된 예외 처리하기

잡히지 않은 예외를 콘솔에 출력하도록 기본 동작을 커스터마이징 할 수 있다. root Coroutine 상의 Context의 요소인 CoroutineExceptionHandler는, root Coroutine과 모든 자식 Coroutine들에 대해 커스텀한 예외 처리가 필요한 경우, 일반 catch 블록으로 사용될 수 있다. 이는 Thread.uncaughtExceptionHandler와 비슷하다. CoroutineExceptionHandler 을 사용해서 예외를 복구 하지는 못한다*1. Coroutine은 Handler가 호출되었을 때 이미 해당 Exception에 대한 처리를 완료했기 때문이다. 일반적으로 CoroutineExceptionHandler는 오류를 로깅하거나, 애러 메세지를 보여주거나, 어플리케이션을 종료하거나 다시 시작하기 위해 사용된다.

 

CoroutineExceptionHandler는 잡히지 않은 예외에 대해서만 실행된다 - 다른 어떠한 방식으로도 처리되지 않은 예외. 특히, 모든 자식 Coroutine들(다른 Job의 Context로 만들어진 Coroutines)은 그들의 예외를 부모 Coroutine에서 처리하도록 위임하는데, 그 부모 또한 부모에게 위임해서 root Coroutine까지 올라간다. 따라서 그들의 Context에 추가된 CoroutineExceptionHandler는 절대 사용되지 않는다. 추가적으로 async 빌더는 모든 예외를 잡아 Deferred 객체에 나타내므로, CoroutineExceptionHandler가 아무런 효과가 없음은 마찬가지이다.

 

📖  Supervision Scope 상에서 실행되는 Coroutine은 예외를 그들의 부모로 전파하지 않으며, 이 규칙으로부터 제외된다. 이 문서에서 이후 다룰 Supervision 섹션에서 더 자세히 알려줄 것이다.
val handler = CoroutineExceptionHandler { _, exception -> 
    println("CoroutineExceptionHandler got $exception") 
}
val job = GlobalScope.launch(handler) { // root coroutine, running in GlobalScope
    throw AssertionError()
}
val deferred = GlobalScope.async(handler) { // also root, but async instead of launch
    throw ArithmeticException() // Nothing will be printed, relying on user to call deferred.await()
}
joinAll(job, deferred)

📌 전체 코드는 이곳에서 확인할 수 있습니다.

 

이 코드의 출력은 다음과 같다 : 

CoroutineExceptionHandler got java.lang.AssertionError

📖 아래 내용은 독자의 이해를 위해 번역자가 추가한 글입니다.

*1. try { ... } catch { ... } 를 쓰면 예외가 발생해도 다음 블록이 실행되는데, CoroutineExceptionHandler를 사용한다고 다음 블록이 실행되는 것은 아니라는 뜻이다.

 


이 글은 Coroutines 공식 문서를 번역한 글입니다.

 

원문 : Coroutine exceptions handling - CoroutineExceptionHandler

원문 최종 수정 :  2022년 6월 27일

 


목차로 돌아가기

 

Kotlin Coroutines 공식 문서 한국어 번역본 : Coroutines 한 번에 정리하기

Kotlin Coroutines 공식 문서 번역을 시작하며 Kotlin Coroutines는 Kotlin을 위한 강력한 비동기 솔루션이다. 안드로이드 실무에서는 한동안 높은 점유율을 자랑한 RxJava를 Coroutines가 대체하고 있으며, 새로

simplecode.kr

 

반응형

'공식 문서 번역 > Coroutines 공식 문서' 카테고리의 다른 글

Coroutine 예외 처리 3편 - Supervision - SupervisorJob, SupervisionScope 사용해 예외 처리하기  (0) 2023.05.13
Coroutine 예외 처리 2편 - Cancellation과 Exceptions, Exceptions 합치기  (0) 2023.05.12
Coroutine Channels 4편 - Buffered channels, Channel은 평등하다, Ticker channels  (0) 2023.03.08
Coroutine Channels 3편 - Fan-out과 Fan-in : Channel이 얼마나 많은 출력, 입력을 만들 수 있는지 알아보기  (0) 2023.03.07
Coroutine Channels 2편 - Channel로 파이프라인 만들기, 파이프라인으로 소수 만들기  (0) 2023.03.06


'공식 문서 번역/Coroutines 공식 문서' 카테고리의 다른 글
  • Coroutine 예외 처리 3편 - Supervision - SupervisorJob, SupervisionScope 사용해 예외 처리하기
  • Coroutine 예외 처리 2편 - Cancellation과 Exceptions, Exceptions 합치기
  • Coroutine Channels 4편 - Buffered channels, Channel은 평등하다, Ticker channels
  • Coroutine Channels 3편 - Fan-out과 Fan-in : Channel이 얼마나 많은 출력, 입력을 만들 수 있는지 알아보기
심플코드
심플코드
프로그래밍을 어렵지 않게 풀어서 설명하는 기술 블로그
    반응형
  • 심플코드
    심플코드
    심플코드
  • 전체
    오늘
    어제
    • 분류 전체보기 (96)
      • 안드로이드를 위한 Coroutines (2)
      • Unit Testing (19)
      • GitHub Actions (0)
      • 공식 문서 번역 (35)
        • Coroutines 공식 문서 (35)
      • 알고리즘 (7)
        • Kotlin 자료구조 (0)
        • 알고리즘 (7)
        • Kotlin으로 구현하는 자료구조 (0)
      • 코딩 테스트 (0)
      • Deep Learning (0)
      • Machine Learning Math (17)
        • Linear Algebra (17)
      • ML (0)
      • Docker (15)
      • Kubernetes (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 코틀린 코루틴의 정석 책 출간 소식
  • 인기 글

  • 태그

    코루틴
    Machine Learning
    mockito
    Kotlin
    Docker
    unit testing
    Coroutines
    Coroutines Context
    코루틴 채널
    junit
    pytorch
    도커
    Coroutines Channel
    coroutine
    코루틴 Flow
    TensorFlow
    컨테이너
    numpy
    unit test
    Coroutines Flow
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
심플코드
Coroutine 예외 처리 1편 - Exception 전파, CoroutineExceptionHandler 사용해 전파된 예외 처리하기
상단으로

티스토리툴바