Coroutines Flow 6편 - Flow 예외 처리, Flow의 예외 투명성

2023. 3. 2. 22:42·공식 문서 번역/Coroutines 공식 문서
반응형

Flow 예외 처리

Flow 수집은 방출하는 곳 혹은 연산자 안의 코드가 예외를 발생시키는 경우 예외와 함께 완료될 수 있다. 예외들을 처리할 수 있는 몇가지 방법이 있다.

 

수집기에서의 try와 catch

수집기는 예외를 처리하기 위해  Kotlin의 try/catch 블록을 사용할 수 있다 :

 

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i) // emit next value
    }
}
​
fun main() = runBlocking<Unit> {
    try {
        simple().collect { value ->         
            println(value)
            check(value <= 1) { "Collected $value" }
        }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}

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

 

이 코드는 collect 터미널 연산자 안에서 성공적으로 예외를 잡아내며, 그 뒤로 더이상 값이 방출되지 않는다 :

 

Emitting 1
1
Emitting 2
2
Caught java.lang.IllegalStateException: Collected 2

 

모든 것이 잡힌다

이전 예제는 방출기나 중간 혹은 터미널 연산자 안에서의 예외들을 모두 잡아낸다. 예를 들어, 방출된 값들이 문자열로 매핑되도록 코드를 바꿔도 코드는 예외를 발생시킨다. 

 

fun simple(): Flow<String> = 
    flow {
        for (i in 1..3) {
            println("Emitting $i")
            emit(i) // emit next value
        }
    }
    .map { value ->
        check(value <= 1) { "Crashed on $value" }                 
        "string $value"
    }

fun main() = runBlocking<Unit> {
    try {
        simple().collect { value -> println(value) }
    } catch (e: Throwable) {
        println("Caught $e")
    } 
}

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

 

예외는 여전히 잡혀서 수집을 중단시킨다.*1

Emitting 1
string 1
Emitting 2
Caught java.lang.IllegalStateException: Crashed on 2

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

*1. 예측하지 못한 곳에서 예외가 나버리면 원하는 결과를 얻기가 어렵기 때문에 문제가 된다. 


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

 

원문 : Asynchronous Flow - Flow exceptions

원문 최종 수정 :  2022년 9월 28일

 


예외 투명성(Exception Transparency)

그러면 어떻게 방출기의 코드가 예외 처리 동작을 캡슐화 할 수 있을까?

 

Flow는 예외에 투명해야 하고, try/catch 블록 내부에서 flow { ... } 빌더의 값을 방출하는 것은 예외 투명성을 위반하는 것이다. 이렇게 하면 예외를 발생시키는 수집기 이전 예제와 같이 언제나 try/catch를 사용해 예외를 잡아낼 수 있다.

 

방출기는 catch 연산자를 사용해 예외 투명성을 유지시키고 예외 처리를 캡슐화 할 수 있다. catch 연산자의 body는 예외를 분석하고, 잡은 예외에 따라 다른 방식으로 대응할 수 있다.

 

  • 예외는 throw를 사용해 다시 throw 될 수 있다.
  • catch의 body에서 emit을 사용해 값을 방출함으로써, 예외를 방출로 바꿀 수 있다.
  • 예외는 무시되거나, 로깅되거나, 다른 코드로 처리될 수 있다.

 

예를 들어, 예외를 잡는 부분에서 텍스트를 방출하도록 해보자 : *1

 

simple()
    .catch { e -> emit("Caught $e") } // emit on exception
    .collect { value -> println(value) }

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

 

투명한 catch

예외 투명도를 존중하는 catch 중간 연산자는 업스트림 예외만을 잡아낸다(catch 윗 부분의 연산자들에서의 예외만을 잡아내고 아래 부분의 예외는 잡아내지 않는다). 만약 collect { ... } 내부의 블록(catch 아래 부분의 코드)이 예외를 발생시키면 예외를 잡아내지 않는다.

 

fun simple(): Flow<Int> = flow {
    for (i in 1..3) {
        println("Emitting $i")
        emit(i)
    }
}

fun main() = runBlocking<Unit> {
    simple()
        .catch { e -> println("Caught $e") } // does not catch downstream exceptions
        .collect { value ->
            check(value <= 1) { "Collected $value" }                 
            println(value) 
        }
}

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

 

catch 연산자가 있음에도 "Caught ..." 메세지가 출력되지 않는다.

 

Emitting 1
1
Emitting 2
Exception in thread "main" java.lang.IllegalStateException: Collected 2
	at ...

 

선언적으로 잡기 

collect 연산자의 body를 onEach 내부로 이동하고 catch 연산자를 그 이후에 위치 시킴으로써, catch 연산자의 선언적인 성질을 모든 예외들을 처리하기 위한 욕구와 결합할 수 있다. collect()를 파라미터 없이 사용함으로써 Flow의 수집을 발생시킬 수 있다.

 

simple()
    .onEach { value ->
        check(value <= 1) { "Collected $value" }                 
        println(value) 
    }
    .catch { e -> println("Caught $e") }
    .collect()

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

 

이제 "Caught ..." 메세지가 출력되는 것을 확인할 수 있고, 명시적으로 try/catch 블록을 사용하지 않고도 모든 예외들을 잡아낼 수 있다.

 

Emitting 1
1
Emitting 2
Caught java.lang.IllegalStateException: Collected 2

 


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

*1. 이 코드의 출력은 다음과 같다. 

Emitting 1
string 1
Emitting 2
Caught java.lang.IllegalStateException: Crashed on 2

2가 방출되면 check(value <= 1)에 의해 illegalStateException이 발생하지만, catch 블록에서 이 예외가 잡아진 후 "Caught java.lang.IllegalStateException: Crashed on 2"로 다시 방출된다. 

 


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

 

원문 : Asynchronous Flow - Exception transparency

원문 최종 수정 :  2022년 9월 28일

 


목차로 돌아가기

 

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

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

simplecode.kr

 

반응형

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

Coroutines Flow 8편 - Flow 실행하기, Flow와 Reactive Stream  (0) 2023.03.04
Coroutines Flow 7편 - Flow 수집 완료 처리하기, Flow 명령적으로 다루기 vs 선언적으로 다루기  (0) 2023.03.03
Coroutines Flow 5편 - 여러 Flow 하나로 합치기, Flow를 Flatten하기 - flatMapConcat, flatMapMerge, flatMapLatest  (0) 2023.03.01
Coroutines Flow 4편 - Flow의 수집이 일어나는 Context, Flow Buffering - buffer, conflate, collectLatest  (0) 2023.02.28
Coroutines Flow 3편 - Flow 터미널 연산자, Flow는 순차적이다  (0) 2023.02.27


'공식 문서 번역/Coroutines 공식 문서' 카테고리의 다른 글
  • Coroutines Flow 8편 - Flow 실행하기, Flow와 Reactive Stream
  • Coroutines Flow 7편 - Flow 수집 완료 처리하기, Flow 명령적으로 다루기 vs 선언적으로 다루기
  • Coroutines Flow 5편 - 여러 Flow 하나로 합치기, Flow를 Flatten하기 - flatMapConcat, flatMapMerge, flatMapLatest
  • Coroutines Flow 4편 - Flow의 수집이 일어나는 Context, Flow Buffering - buffer, conflate, collectLatest
심플코드
심플코드
프로그래밍을 어렵지 않게 풀어서 설명하는 기술 블로그
    반응형
  • 심플코드
    심플코드
    심플코드
  • 전체
    오늘
    어제
    • 분류 전체보기 (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)
  • 블로그 메뉴

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

  • 공지사항

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

  • 태그

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

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
심플코드
Coroutines Flow 6편 - Flow 예외 처리, Flow의 예외 투명성
상단으로

티스토리툴바