본문 바로가기
Android/Coroutine

[Android/Coroutine] launch vs async 차이점 정리

by quessr 2025. 2. 19.

 

Coroutine에서 launch와 async는 모두 새로운 코루틴을 시작하는 데 사용되지만, 반환값을 처리하는 방식이 다릅니다.

이 글에서는 공부한 내용을 정리하며, launch와 async의 차이를 코드 예제와 함께 살펴보겠습니다.


1. launch: 결과를 반환하지 않는 Job

val job = GlobalScope.launch {
    delay(1000L)
    println("launch 완료!")
}
job.join() // 완료될 때까지 대기

특징

  • launchJob을 반환합니다.
  • Job은 단순히 실행을 시작하고, join()을 호출하기 전까지는 실행 완료 여부를 기다리지 않습니다.
  • launch는 비동기적으로 실행되지만, 결과 값을 반환하지 않습니다.
  • 즉, 실행은 하지만 결과를 받아서 처리하는 용도가 아닙니다.

2. async: 결과를 반환하는 Deferred

val deferred = GlobalScope.async {
    delay(1000L)
    "async 완료!"
}
val result = deferred.await() // 결과값을 받을 때까지 대기
println(result)

특징

  • asyncDeferred<T> 객체를 반환합니다.
  • Deferred<T>await()을 호출하면 실행이 완료될 때까지 대기하고 결과 값을 반환합니다.
  • 즉, async결과 값을 반환받아야 할 때 사용합니다.

3. launch vs async 비교

특징 launch async
반환 값 없음 (Job 반환) 있음 (Deferred<T> 반환)
실행 방식 비동기 실행 후 결과를 기다리지 않음 await() 호출 시 결과 반환
예외 전파 즉시 전파됨 await() 호출 시 전파됨
사용 예시 단순 실행 결과 값을 받아야 할 때

4. 언제 사용해야 할까요?

  • 단순히 백그라운드에서 실행하고 싶다면 → launch
  • 비동기 함수의 결과 값을 받아야 한다면 → async

예제: launchasync를 함께 사용하기

suspend fun fetchData(): String {
    delay(1000L)
    return "데이터 로드 완료!"
}

suspend fun main() = coroutineScope {
    val job = launch {
        println("launch 실행 중...")
        delay(500L)
        println("launch 완료!")
    }

    val deferred = async { fetchData() }

    job.join() // launch가 끝날 때까지 대기
    val result = deferred.await() // async의 결과를 받음

    println(result)
}

 

실행 흐름:

  1. launch가 실행됨 → 500ms 후 "launch 완료!" 출력
  2. async 실행 (fetchData() 호출) → 1000ms 후 "데이터 로드 완료!" 출력
  3. await()을 호출하면 결과 값을 반환받음

5. 추가 설명

1) async는 결과 값을 반환해야 하므로 반드시 await()을 호출해야 합니다.

  • Deferred<T>를 반환하므로 await()을 호출해야 최종 결과를 받을 수 있습니다.
  • 결과를 기다리기 때문에 자동으로 완료될 때까지 기다리는 효과가 있습니다.

2) launch는 단순 실행용이며, 기본적으로 완료될 때까지 기다릴 필요가 없습니다.

  • Job을 반환하지만, join()을 호출하지 않으면 실행이 끝날 때까지 기다리지 않습니다.
  • 따라서, 순차 처리가 필요할 때는 join()을 호출해서 실행 완료를 보장해야 합니다.

6. Job과 Deferred의 차이

Job: 코루틴의 실행 상태를 관리하는 객체

  • launchJob을 반환하지만, 결과 값을 반환하지 않습니다.
  • job.join()을 호출하면 코루틴이 끝날 때까지 기다리지만, 결과를 받을 수는 없습니다.

Deferred: 결과 값을 포함하는 비동기 객체

  • asyncDeferred<T>를 반환하며, await()을 호출하면 실행 결과를 받을 수 있습니다.

예제:

val job = launch {
    delay(1000L)
    println("launch 완료!")
}
println(job) // kotlinx.coroutines.JobImpl@xxxx

val deferred = async {
    delay(1000L)
    "async 완료!"
}
val result = deferred.await()
println(result) // async 완료!
  • launch는 실행만 담당하고 결과를 반환하지 않음
  • async는 실행 후 await()을 통해 결과를 받을 수 있음

8. 결론

  • launch는 실행만 하고 결과를 반환하지 않으며, Job을 반환하여 실행 상태를 관리할 수 있습니다.
  • asyncDeferred<T>를 반환하고, await()을 호출해야 실행 결과를 받을 수 있습니다.
  • launch는 단순 실행용이며, async는 결과 값이 필요한 경우 사용합니다.
  • Job은 실행 상태를 관리하는 객체이며, Deferred<T>는 실행 결과를 포함하는 비동기 객체입니다.
반응형