팀 내에서 코루틴 병렬처리와 관련하여 코드리뷰 중 팀원간 싱크가 맞지 않는 것 같아 정리한 글입니다.

연속성(Concurrency)

1번

suspend fun main() = coroutineScope {
    async { someService.callAPI1() }.await()
    async { someService.callAPI2() }.await()
}
  • 위 코드는 두 API 호출이 순차적으로 이루어집니다.
  • 첫 번째 async 블록은 callAPI1()를 호출하고, 그 결과를 기다린 후, 두 번째 async 블록이 시작됩니다.
  • 이 방식은 두 번째 API 호출이 첫 번째 API 호출의 결과에 의존적인 경우 또는 순차적 실행이 필요한 경우에 사용하기 적합합니다.

 

2번

suspend fun main() = coroutineScope {
    async {
        someService.callAPI1()
        someService.callAPI2()
    }.await()
}
  • 위 코드는 두 API 호출은 단일 async 블록 내에서 순차적으로 실행됩니다.
  • 이는 1번 코드와 유사한 동작을 보이지만, 두 호출이 같은 코루틴 컨텍스트 내에서 실행되기 때문에 내부적인 차이가 있습니다.
  • 1번과 마찬가지로 이 방식은 두 번째 호출이 첫 번째 호출의 결과에 의존적인 경우에 사용하기 적합합니다.

 

병렬성(Parallelism)

3번

suspend fun main() = coroutineScope {
    listOf(
        async { someService.callAPI1() },
        async { someService.callAPI2() }
    ).awaitAll()
}
  • 두 API 호출 (callAPI1()와 callAPI2())은 별도의 async 블록 내에서 병렬로 시작됩니다.
  • 이는 두 API 호출이 거의 동시에 시작되도록 합니다.
  • awaitAll()은 두 작업이 모두 완료될 때까지 기다립니다.
  • 이 방식은 두 호출 사이에 의존성이 없고 최대한 빠르게 둘 다 완료하려는 경우에 사용하기 적합합니다.

 

4번

suspend fun main() = coroutineScope {
    val a = async {
        someService.callAPI1()
    }
    val b = async {
        someService.callAPI2()
    }
    a.await()
    b.await()
}
  • 두 API 호출은 별도의 async 블록에서 시작되나, a.await()와 b.await()의 순서에 따라 결과를 기다리는 순서가 정해집니다.
  • 여기서는 a.await()이 먼저 있으므로, callAPI1()의 결과를 먼저 기다리고, 그 후 callAPI2()의 결과를 기다립니다. 하지만 실제로 위 3번과 같이 callAPI1()와 callAPI2()는 병렬로 실행됩니다.
  • 이 방식은 두 호출의 병렬 실행과 결과 처리 순서에 대한 제어를 동시에 원하는 경우에 적합합니다.