-
async-awaitBackEnd/coroutine 2025. 6. 8. 05:00반응형
async와 Deferred
- async 코루틴 빌더를 호출하면 코루틴이 생성되고, Deferred<T> 타입 객체가 반환됩니다.
- Deferred는 Job과 같이 코루틴을 추상화한 객체이지만, 코루틴으로부터 생성된 결과값을 감싸는 기능을 추가로 가집니다.
- 결과값의 타입은 제네릭 타입인 T로 표현됩니다.
public fun <T> CoroutineScope.async( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ): Deferred<T>
async vs launch
- async 함수도 launch 함수와 마찬가지로
- context 인자로 CoroutineName이나 CoroutineDispatcher 설정이 가능합니다.
- start 인자로 CoroutineStart.LAZY를 설정해 지연 코루틴을 만들 수 있습니다.
- async 함수가 launch 함수와 다른 점은 block 람다식이 T를 반환한다는 점과 반환 객체가 Deferred라는 점입니다.
public fun <T> CoroutineScope.launch( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job
Deferred
- Deferred는 Job의 서브타입으로, 코루틴으로부터의 결과값 수신을 위해 몇가지 함수만 추가된 인터페이스입니다.
public interface Deferred<out T> : Job
- Deferred 객체는 Job 객체의 모든 함수와 프로퍼티를 사용할 수 있습니다.
Deferred 객체의 제네릭 타입 지정
Deferred 객체의 제네릭 타입을 지정하기 위해서는 Deferred에 명시적으로 타입을 설정하고, async 람다식에 반환값을 설정하면 됩니다.
import kotlinx.coroutines.* fun main() = runBlocking<Unit> { val networkDeferred = async(Dispatchers.IO) { delay(1000L) // 네트워크 요청 return@async "Dummy Response" // Dummy Response 반환 } }
Deferred 객체의 동작 방식
- Deferred 객체는 미래의 어느 시점에 결과값이 반환될 수 있음을 표현하는 코루틴 객체입니다.
- 코루틴이 실행 완료되었을 때 결과값이 반환되므로 언제 수신될 지 알 수 없습니다.
- 결과값이 필요하다면 결과값이 수신될 때까지 대기해야 합니다.
- Deferred 객체의 await 함수를 호출하면 Deferred 코루틴이 실행 완료될 때까지 await 함수를 호출한 코루틴이 일시 중단됩니다.
- Deferred 코루틴이 실행 완료되면 결과값이 반환되고 호출부의 코루틴이 재개됩니다.
import kotlinx.coroutines.* fun main() = runBlocking<Unit> { val networkDeferred: Deferred<String> = async(Dispatchers.IO) { delay(1000L) // 네트워크 요청 return@async "Dummy Response" // Dummy Response 반환 } val result = networkDeferred.await() // 결과값이 반환될 때까지 runBlocking 일시 중단 println(result) // 결과값 출력 }
복수의 코루틴으로부터 결과값 수신하기
다음 코드는 두 개의 코루틴을 실행하고 결과를 수신하는 예제입니다. 코드를 실행하여 출력 결과를 확인해보면 순차적으로 실행된 것을 확인할 수 있습니다. 이는 async-await이 연속적으로 호출됐기 때문입니다.
import kotlinx.coroutines.* fun main() = runBlocking<Unit> { val startTime = System.currentTimeMillis() // 1. 시작 시간 기록 // 2. 플랫폼1에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred1: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("철수","영수") } val participants1 = participantDeferred1.await() // 3. 결과가 수신 될 때까지 대기 // 4. 플랫폼2에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred2: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("영희") } val participants2 = participantDeferred2.await() // 5. 결과가 수신 될 때까지 대기 // 6. 지난 시간 표시 및 참여자 목록을 병합해 출력 println("[${getElapsedTime(startTime)}] 참여자 목록: ${listOf(*participants1, *participants2)}") } fun getElapsedTime(startTime: Long): String = "지난 시간: ${System.currentTimeMillis() - startTime}ms"
// 출력 결과 [지난 시간: 2024ms] 참여자 목록: [철수, 영수, 영희]
코루틴을 병렬로 실행하기 위해서는 코루틴을 모두 실행한 다음 await을 호출해야 합니다.
import kotlinx.coroutines.* fun main() = runBlocking<Unit> { val startTime = System.currentTimeMillis() // 1. 시작 시간 기록 // 2. 플랫폼1에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred1: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("철수","영수") } // 3. 플랫폼2에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred2: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("영희") } val participants1 = participantDeferred1.await() // 4. 결과가 수신 될 때까지 대기 val participants2 = participantDeferred2.await() // 5. 결과가 수신 될 때까지 대기 // 6. 지난 시간 표시 및 참여자 목록을 병합해 출력 println("[${getElapsedTime(startTime)}] 참여자 목록: ${listOf(*participants1, *participants2)}") } private fun getElapsedTime(startTime: Long): String = "지난 시간: ${System.currentTimeMillis() - startTime}ms"
// 출력 결과 [지난 시간: 1014ms] 참여자 목록: [철수, 영수, 영희]
awaitAll 함수
- awaitAll을 사용하면 복수의 Deferred 객체로부터 결과값을 수신할 수 있습니다.
- awaitAll 함수는 가변 인자로 Deferred 타입의 객체를 받아 인자로 받은 모든 Deferred로부터 결과가 수신될 때까지 호출부의 코루틴을 일시 중단합니다.
import kotlinx.coroutines.* fun main() = runBlocking<Unit> { val startTime = System.currentTimeMillis() // 1. 시작 시간 기록 // 2. 플랫폼1에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred1: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("철수", "영수") } // 3. 플랫폼2에서 등록한 관람객 목록을 가져오는 코루틴 실행 val participantDeferred2: Deferred<Array<String>> = async(Dispatchers.IO) { delay(1000L) return@async arrayOf("영희") } // 4. 두 개의 코루틴으로부터 결과가 수신될 때까지 대기 val results = awaitAll(participantDeferred1, participantDeferred2) // val results = listOf(participantDeferred1, participantDeferred2).awaitAll() // Collection 확장함수 // 5. 지난 시간 표시 및 참여자 목록을 병합해 출력 println("[${getElapsedTime(startTime)}] 참여자 목록: ${listOf(*results[0], *results[1])}") } private fun getElapsedTime(startTime: Long): String = "지난 시간: ${System.currentTimeMillis() - startTime}ms"
반응형'BackEnd > coroutine' 카테고리의 다른 글
CoroutineContext (1) 2025.06.15 withContext (0) 2025.06.14 Coroutine 상태 (1) 2025.06.07 Coroutine 취소 (0) 2025.06.01 지연 Coroutine (0) 2025.05.31