시배's Android

Kotlin Coroutines Deep Dive | 10장. 예외처리 본문

Book/Kotlin Coroutines Deep Dive

Kotlin Coroutines Deep Dive | 10장. 예외처리

si8ae 2024. 1. 31. 21:39
  • 코루틴 빌더는 부모도 종료시키며, 취소된 부모는 자식들 모두를 취소시킨다는 점입니다.
  • 코루틴이 종료되기 전에 예외를 잡는 건 도움이 되지만, 조금이라도 늦으면 이미 손쓸 수 없는 상황이 되어 버립니다.
  • 코루틴 간의 상호작용은 잡을 통해서 일어나기 때문에, 코루틴 빌더 내부에서 새로운 코루틴 빌더를 try-catch 문을 통해 래핑하는 건 전혀 도움이 되지 못합니다.

SupervisorJob

  • SupervisorJob을 사용하면 자식에서 발생한 모든 예외를 무시할 수 있습니다.
fun main() = Unit = runBlocking {
	//이렇게 하지 마세요. 자식 코루틴 하나가 있고
    //부모 코루틴이 없는 잡은 일반 잡과 동일하게 작동합니다.
    launch(SupervisorJob()) { //1
    	launch {
        	delay(1000)
            throw Error("some error")
        }
        
        launch {
        	delay(2000)
            println("Will not be printed")
        }
    }
    
    delay(3000)
}

하나의 코루틴이 취소되어도 다른 코루틴이 취소되지 않는다는 점에서, 같은 잡을 다수의 코루틴에서 컨텍스트로 사용하는 것이 좀더 나은 방법입니다.

supervisorScope

  • 예외 전파를 막는 또 다른 방법은 코루틴 빌더를 supervisorScope로 래핑하는 것입니다.
  • supervisorScope는 단지 중단 함수일 뿐이며, 중단 함수 본체를 래핑하는 데 사용됩니다.
  • 예외 전파를 멈추는 또 다른 방법은 coroutineScope를 사용하는 것입니다. 이 함수는 코루틴 빌더와 달리 부모에 영향을 미치는 대신 try-catch를 이용해 잡을 수 있는 예외를 던집니다.
//이렇게 하면 안됩니다!!
suspend fun sendNotifications(
	notifications : List<Notification>
) = withContext(SupervisorJob()) {
	for (notification in notifications) {
    	launch {
        	client.send(notification)
        }
    }
}
  • SupervisorJob이 withContext의 부모가 됩니다.
  • 자식 코루틴에서 예외가 발생하면 withContext 코루틴으로 전달이 되며, Job이 취소되고, 자식 코루틴 또한 전부 취소되며, 마지막으로 예외가 던져집니다.

CancellationException은 부모까지 전파되지 않는다.

  • 예외가 CancellationException의 서브클래스라면 부모로 전파되지 않습니다.
  • 현재 코루틴을 취소시킬 뿐입니다.

코루틴 예외 핸들러

  • 예외를 다룰 때 예외를 처리하는 기본 행동을 정의하는 것이 유용할 때가 있습니다.
  • 이럴 경우 CoroutineExceptionHandler 컨텍스트를 사용하면 편리합니다.
  • 예외 전파를 중단시키지 않지만 예외가 발생했을 때 해야 할 것들을 정의하는 데 사용할 수 있습니다.