coroutineScope 함수를 사용한 예외 처리
·
Study/Kotlin
이번 글에서는 coroutineScope라는 함수를 사용해서 예외를 처리해보도록 하겠다. 대소문자를 잘 구별해야한다. 대문자로 시작하는 CoroutineScope 함수와는 사뭇 다르다. 예외 발생 상황 보기fun main() = runBlocking { launch { throw RuntimeException() }}나는 위와 같은 코드를 실행해서 예외를 발생시킬 것이다. 당연히 launch에서 발생한 예외는 try-catch나 CoroutineExceptionHandler가 없기에비정상 종료로 이어질 것이다. try-catch로 처리해볼까?fun main() = runBlocking { try { launch { throw RuntimeException() } ..
launch vs async in Coroutines Exception Handling
·
Study/Kotlin
이번 글에서는 코루틴에서 예외를 처리할 때 launch와 async 코루틴 빌더의 차이를 살펴보려고 한다. launch 사용 예제val scope = CoroutineScope(Job())scope.launch { delay(100) throw RuntimeException()}Thread.sleep(300)이 코드를 실행하면 어떤 결과가 나올까?예외를 처리하는 부분은 없다.콘솔 창에서 볼 수 있듯 예외가 전파되어 종료되었다. async 사용 예제val scope = CoroutineScope(Job())scope.async { delay(100) throw RuntimeException()}Thread.sleep(300)이번에는 단순히 launch를 async로 바꿔보았다. 실행 결과는 과연..
Coroutines try-catch vs ExceptionHandler
·
Study/Kotlin
이번 글에서는 try-catch와 ExceptionHandler를 비교해보려고 한다. 얼핏 보기에는 둘 다 예외 처리의 기법으로만 보고 넘어갈 수도 있지만,각각 사용해야하는 상황이 다르기 때문이다. try-catch 관점try-catch는 예외가 발생하고나서도 계속 작업이 필요한 경우에 사용된다. 예를 들면, 코루틴 내부에서 재시도하는 로직이 필요한 경우이다. try-catch 구문을 사용해 예외를 잡아내고 해당 예외를 다시 전파시키지 않는다면예외는 상위 계층으로 전파되지 않는다.(부모 코루틴에게 전파되지 않는다) 예외가 발생했음에도 상위 계층으로 예외가 전파되지 않는다면Structured Concurrency를 해칠 수 있다. ExceptionHandler 관점try-catch와는 달리 계속해서 작업이..
Exception Handling Using ExceptionHandler in Coroutines
·
Study/Kotlin
이번에는 CoroutineExceptionHandler로 예외 처리를 해보도록 하자. 기존 try-catch 구문과는 어떤 차이가 있는지도 볼 예정이다. 처리할 코드val scope = CoroutineScope(Job())scope.launch { throw RuntimeException()}Thread.sleep(1000) CoroutineExceptionHandler 사용 지점이 핸들러는 Coroutine의 Context 요소이다. 이전 글에서의 기억을 떠올려본다면 가장 대표적인 Context 요소는 Dispatcher일 것이다. 또한, '+' 연산자를 사용하면 여러 Context 요소를 사용할 수 있다. 그럼 위 코드에서 어떤 위치에 핸들러를 주입해야할까? 정답은 두 위치에서 가능한데, 하나는 J..
Exception Handling Using try-catch Clause in Coroutines
·
Study/Kotlin
이번 글은 코루틴에서 try-catch절을 사용해 예외 처리를 해보는 시간이 될 것이다. 일반적인 예외 처리 상기하기fun main() { generateException()}fun generateException() { throw RuntimeException()}이런 예외를 try-catch절로 처리한 상황과 그렇지 않은 상황을 떠올려보자. 먼저 예외 처리를 해두었다면 프로그램이 정상적으로 실행이 종료된다. 그렇지 않은 경우 로그를 남기며 프로그램에 크래시가 발생한다. 코루틴에 적용해보기fun main() { val scope = CoroutineScope(Job()) scope.launch { generateException() } Thread.sleep(100)}fu..
NonCancellable Coroutines 사용해보기
·
Study/Kotlin
이전 글에서 코루틴을 취소하는 방법에 대해 설명해보았다. 여기서 생각해볼만한 것이 하나 있는데 바로 CancellationException을 사용해코루틴을 종료시키기 직전 특정 작업을 하는 경우이다. 더 정확히 따지면 suspend function 호출이 필요하지만 불가능한 경우이다. 예제 코드와 같이 보자. 예제 코드fun main() = runBlocking { val job = launch(Dispatcher.Default) { repeat(10) { index -> if (isActive) { println("repeat $index") Thread.sleep(100) } else { ..
Coroutines Cooperative Cancellation
·
Study/Kotlin
이번 글에서는 코루틴을 취소할 때 어떤 취소 방법을 취해야하는지에 대해 설명해본다. 코루틴 안에서 반복문을 실행하는 도중 취소하는 상황을 예시로 보자. 코드 예제fun main() = runBlocking { val job = launch(Dispatcher.Default) { repeat(10) { index -> println("repeat $index") Thread.sleep(100) } } delay(250) println("Cancel coroutine") job.cancel()}위 예제를 실행한 결과를 먼저 예상해보자. 만약 이 코드가 정상적으로 repeat 0~2까지만 실행됐을거라고 생각했다면 오산이다. 취소..
LifecycleScope 간단히 알아보기
·
Study/Kotlin
이번 글에서는 LifecycleScope를 소개해본다. 다만 제목 그대로 간단히 알아보려 하는데 이전 글에서 알아본 ViewModelScope와 비슷하기 때문이다. LifecycleScope의 lifecycle 알아보기생명주기는 생각보다 심플하다.  Lifecycle owner가 살아있는 동안 해당 스코프도 살아있게 된다. 상황에 따라 Activity, Fragment 등이 될 수 있다. 해당 owner가 destroy될 때 LifecycleScope에서 실행된 모든 코루틴은 cancel된다. 가장 대표적인 destroy 상황은 화면 회전에 의한 Activity destroy이다. 이렇게 되면 특정 작업을 수행하다가도 cancel되어버리는 상황이 발생하기에이런 경우, ViewModelScope를 사용하는..
ViewModelScope 알아보기
·
Study/Kotlin
이번에는 드디어 이전 예제들에서 사용해왔던 viewModelScope에 대해 알아보도록 하자. ViewModelScope LifecycleviewModelScope는 ViewModel의 lifecycle과 연관되어 있다. 다르게 말하면 viewModelScope에서 시작된 코루틴은 ViewModel이 살아있는 경우 계속 실행된다. 당연히 ViewModel onCleared 메소드가 호출되는 시점에viewModelScope에서 시작된 코루틴은 모두 cancel된다. ViewModelScope 구현 살펴보기이 스코프는 ViewModel이 clear될 때 자동으로 cancel된다는위의 lifecycle 설명에서 말했던 부분이 보인다. Dispatcher 확인하기MainCoroutineDispatcher.imm..
GlobalScope 알아보기
·
Study/Kotlin
GlobalScope에 대해 설명하기 전 가장 저명한 사실을 하나 얘기하고 시작한다. 우리는 앱에서 GlobalScope를 사용할 일이 거의 없을 것이다. 공식문서에서도 되도록 사용하지 않는 것을 권장하는 뉘앙스를 풍긴다. 사용하지 않을 이유 찾기 제한된 수명 주기가 없다.이 뜻을 앱 관점에서 보면 GlobalScope 안에서 시작된 코루틴은앱 프로세스가 종료될 때까지 종료되지 않는다는 것이다. 어떠한 Job에도 엮이지 않는다.제목 그대로를 코드로 확인해보자.println("GlobalScope Job: ${GlobalScope.coroutineContext[Job]}")이 코드를 실행시켜보자.GlobalScope Job: null위와 같은 결과가 나온다. 위 결과로 유추할 수 있는 것이 또 하나가 생겼..