Image
Coroutines/Coroutine Basics

[Coroutine] 10. Deferred를 이용한 결과값 수신

Deferred란

Deferred는 직역하면 연기라는 뜻을 가진다. "결과값 수신을 연기한다"라는 뜻인데, 이는 미래의 어느 시점에 결과값이 올 것을 뜻한다.

 

Deferred의 의미와 같이 "Deferred는 결과값을 수신하는 비동기 작업" 이라고 정의될 수 있다.

 

 

Deferred는 Job이다.

public interface Deferred<out T> : Job {
    public suspend fun await(): T
    public val onAwait: SelectClause1<T>
    ..
}

Deferred는 결과가 있는 비동기 작업을 수행하기 위해 결과 값이 없는 Job을 확장하는 인터페이스이다. 즉, Deferred는 Job이며, 이로 인해 Deferred는 Job의 모든 특성을 갖는다. 8번 글이었던 Job의 상태 변수(isActive, isCancelled, isCompleted)와 9번 글이었던 Job의 Exception Handling 등을 모두 Deferred에서 똑같이 적용할 수 있다.

*Job은 Deferred가 아니다.

 

Deferred의 생성

Deferred는 코루틴 async 블록을 이용해 생성될 수 있다. Deferred의 결과값을 직접 조작하는 CompletableDeferred 또한 있지만, 범위를 넘어가니 이번 글에서는 다루지 않도록 한다.

suspend fun main() {
    val deferred: Deferred<Int> = CoroutineScope(Dispatchers.IO).async {
        30
    }
}

 

async블록의 마지막줄의 값이 Deferred로 Wrapping되며(위에서는 Deferred<Int>) 이 값이 바로 Deferred의 결과값이 된다.

 

자 이제 결과값을 어떻게 수신받는지 알아보자.

 

Deferred에서 결과값 수신 : await()

Deferred에서 결과값을 수신하기 위해서는 Deferred인터페이스 상의 await()메서드를 이용한다.

 

예를 들어 아래와 같이 "Deferred Result"라는 String을 수신할 것으로 예상되는 Deferred가 있다고 해보자. 드 상에서 await()을 호출하면 runBlocking 코루틴은 IO Thread로부터 Deferred의 결과가 수신될 때까지 일시중단된다. 

fun main() = runBlocking<Unit> {
  val deferred: Deferred<String> = async(Dispatchers.IO) {
    "Deferred Result"
  }

  val deferredResult = deferred.await() // deferred에서 결과가 올 때까지 일시중단

  println(deferredResult)
}

 

따라서 위 코드를 실행하면 아래 <그림1>과 같은 결과값이 출력된다.

그림1. Deferred에 await()사용하기

 

 

Deferred가 Job과 다른점

 Deferred가 Job과 다른 점이 있다면, Deferred는 예외를 전파할 뿐만 아니라 예외를 노출하기도 한다는 점이다. Deferred는 결과값 수신을 대기하기 위해 특수한 메서드 await()를 사용하는데 await() 호출 시 만약 Deferred 코루틴에 예외가 발생했을 경우 예외가 노출된다.

 

다음과 같은 코드를 살펴보자.

fun main() = runBlocking<Unit> {
  val deferred: Deferred<String> = async(Dispatchers.IO) {
    throw IllegalArgumentException()
  }

  try {
    val deferredResult = deferred.await() // deferred에서 결과가 올 때까지 일시중단
  } catch (e: Exception) {
    println(e)
  }
}

이 코드를 실행하면, 다음과 같은 결과가 나온다.

첫 번째 줄은 await 호출 시 노출된 예외가 try catch 문에 잡혀서 나오는 예외이고, 두 번째 줄은 deferred 코루틴에 예외가 발생해 runBlocking 코루틴까지 전파되어 발생된 예외이다.

 

즉, Deferred 코루틴은 예외를 상위 코루틴으로 전파할 뿐만 아니라, await 호출 시 노출시키기도 한다.

 

 

요약

Deferred는 예외를 전파할 뿐만 아니라 노출하기도 한다.

 

 

Kotlin Coroutines 공식 기술 문서 번역이 GitHub 오픈소스로 배포되었습니다. Starganizer가 되어 오픈소스를 지지해주세요.

 

Kotlin Coroutines 공식 문서 번역을 시작하며 · GitBook

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

seyoungcho2.github.io

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com