[Kotlin][Coroutine] Async, Await, Deferred, withContext

 

 

본 글은 조세영님의 <코틀린 코루틴의 정석>을 읽고 이를 바탕으로 작성되었습니다.

 

 

 

저번 포스트에서 코루틴 빌더 launch, runBlocking과 그 처리, 취소, 상태에 대해 알아보았다면, 이번 포스트에서는 새로운 코루틴 빌더 async와 그 쓰임에 대해 알아보도록 하자.

 

먼저 이전 포스트의 launch, runBlocking을 복습하고 async에 대해 알아보자. 코루틴 빌더 함수는 다음과 같다. 

 

 

코루틴 빌더 함수

 

  • launch: 새로운 코루틴을 시작하고 결과값이 없는 코루틴 객체인 job을 반환한다. 
  • async: 새로운 코루틴을 시작하고 결과값이 있는 코루틴 객체인 deferred를 반환한다.
  • runBlocking: 현재 스레드를 블록하고 코루틴을 시작한다.

 

 

위와 같이 launch를 사용하면 새로운 코루틴을 시작할 수 는 있지만 그 결과는 job이어서 받아올 수 없었다. 하지만 async는 deferred를 반환하므로 그 결과를 받아와서 처리할 수 있다는 차이가 있다.

 

 

 

그럼 async는 어떤식으로 사용할까 ?

 

async를 사용해 Deferred 만들기

public fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> T
): Deferred<T>

 

위와 같이 async 또한 context, start, block 의 세가지 인자를 가질 수 있다. 차이는 반환형식이 Deferred 라는 것이다. 

 

 

 

 

그렇다면 Deferred 객체에 대해서 알아보자.

 

Deferred 객체

  • 미래의 어느시점에 결과값이 반환될 수 있음을 표현하는 코루틴 객체 → 결과값을 반환받는 기능이 추가된 job 객체의 특별한 형태이다 (job 인터페이스의 서브타입)
  • 코루틴이 실행완료될때 결과값이 반환되므로 언제인지는 정확히 알 수 없고, 수신될때까지 대기해야한다

이처럼 deferred는 결과값 반환 시점을 알 수 없으므로 대기해야하는데, 이때 대기를 위해 사용되는 함수가 await이다.

 

 

await

  • await 함수는 await의 대상이된 deferred 객체의 실행이 완료될때까지 await가 호출된 코루틴을 일시 중단하고, 완료하면 반환한다
  • 요약하면, deferred 객체의 await 함수는 코루틴이 실행 완료될때까지 호출부의 코루틴을 일시 중단한다. 

 

 

withContext로 async-await 대체하기

fun main() = runBlocking<Unit> {
  val result: String = withContext(Dispatchers.IO) {
    delay(1000L) // 네트워크 요청
    return@withContext "Dummy Response" // 문자열 반환
  }
  println(result)
}

 

코루틴 라이브러리에서는 withContext를 제공해 async-await를 대체할 수 있다.

 

 

 

 

그렇다면 async-await 와 withContext는 어떤 차이를 가질까 ? 

 

async-await VS withContext

async-await

  • 새로운 코루틴을 생성해 작업을 처리한다

→ 새로운 코루틴을 만들지먄 await로 순차처리가 가능해 동기적 처리가 가능

withContext

  • 실행중이던 코루틴을 유지한채로 코루틴의 실행환경만 바꿔서 작업을 처리
  • 즉 코루틴을 만드는 대신 기존의 코루틴에서 CoroutineContext만 바꿔서 처리한다. 위 예제는 IO니까 백그라운드스레드에서 실행
  • withContext의 컨텍스트로 변경된다. 즉 Context Switching (문맥교환)이 일어난다.
  • 작업 모두 실행하면 이전의 실행환경으로 복귀한다.

→ 코루틴이 유지된 채로 코루틴을 실행하는 실행스레드만 변경되므로 동기적 처리가 가능