본문 바로가기
Android.Kotlin

[Android] Coroutine Builder, Suspend 함수 이해하기

by 동동하다 2023. 9. 11.
반응형

코루틴을 사용하기 위해서 CoroutineScope 를 생성했다면 Coroutine Builder 를 통해 코루틴을 실행할 수 있습니다. Coroutine Builder 에는 launch(), async() 등 있습니다. 

Suspend 함수의 경우 말 그대로 일시중단 을 의미합니다. launch(), async() 로 실행한 코루틴은 내부적으로 작업이 종료될 때까지 코루틴이 일시중단 됩니다. 이 때 실행되어야 하는 로직이 코루틴 내부에 존재하지 않고 외부 함수로 존재한다면, 해당 함수가 일시중단 (suspend) 된다는 표시를 해주기 위해 사용하는 키워드 입니다.

 

launch

코루틴을 실행할 때 내부적으로 비동기 처리가 되지만 결과 반환 값이 없을 때 launch 를 사용합니다. 사실 결과 값이 없을 뿐이지 launch 를 실행하면 Job 을 반환하게 됩니다.

runBlocking {
    val job:Job = launch {
        delay(1000)
        println("hello world")
    }

    println("start")
}

위 코드를 실행하게 되면 start 가 먼저 실행되고 1초 뒤에 hello world 가 실행됩니다. 

 

async

launch 와 반대로 async 는 결과 값이 존재할 때 사용합니다. 해당 결과 값은 Deferred 타입으로 리턴되며, Deferred 값은 코루틴 결과 반환되는 리턴값을 담을 수 있는 객체라고 보면 됩니다.

runBlocking {
    val asyncTest = async<String> {
        delay(1000)
        println("in async...")
        "hello world"
    }

    println("start")
    val result = asyncTest.await()
    println("result of async is [$result]")
    println("end")
}

위 코드 실행 결과는 아래와 같습니다.

2023-09-11 17:36:57.500 10102-10102 System.out        I  start
2023-09-11 17:36:58.506 10102-10102 System.out        I  in async...
2023-09-11 17:36:58.511 10102-10102 System.out        I  result of async is [hello world]
2023-09-11 17:36:58.512 10102-10102 System.out        I  end

async 은 await 키워드와 함께 사용해야 합니다. async 로 생성된 deferred 를 실행하기 위해서는 await 함수를 통해 실행시켜주어야 합니다.

await 로 실행된 코루틴은 비동기 처리가 완료되기까지 기다립니다. 그리고 비동기 처리가 완료되면 다음을 실행하게 됩니다.

 

suspend

위에 예시로 든 비동기 처리들은 모두 코루틴 블록 내부에 정의되어 있습니다. 하지만 비동기 처리하는 로직이 복잡해지고, 코드수가 길어지면 해당 로직을 별도의 함수로 분리해야 하는 경우가 발생할 수 있습니다. 이 때 분리된 함수앞에 suspend 라는 키워드를 통해 해당 함수가 코루틴을 작업하는 함수임을 명시해주어야 합니다.

suspend fun suspendTest() {
    val job = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        println("in async...")
        "hello world"
    }

    println("start")
    val result = job.await()
    println("result of async is [$result]")
    println("end")
}

여기서 suspend 로 정의된 함수를 수행하기 위해서 일반 함수에서 사용하면 어떻게 될까요?

마찬가지로 오류가 발생합니다.

suspend 로 정의된 함수도 코루틴 내부에서 실행시켜주어야 합니다. 

runBlocking {
    suspendTest()
}
반응형