Android/Asynchronous

[Asynchronous] suspend 넌 코루틴이 아니야

종종인 2024. 8. 12. 15:05

suspend fun 이란??

- suspend fun

suspned fun은 일시 중단이 가능한 함수로 함수 내에 일시 중단 지점을 포함할 수 있는 함수이다. 코루틴에서 실행되는 일시 중단 지점이 포함된 코드를 재사용할 수 있는 코드의 집합으로 만드는 역할을 한다.

 

이해하기 쉽게 아래의 코드로 설명해 보겠다.

fun main() = runBlocking<Unit> {
    delay(100L)
    println("Hello World")
    delay(100L)
    println("Hello World")
}

 

위의 코드는 delay 함수와 println 함수가 반복된다. 반복되는 코드를 줄이기 위해 이를 함수로 만들자면 아래와 같이 만들 수 있다.

fun printHelloWorldDelay() {
    delay(100L)
    println("Hello World")
}

 

하지만 일시 중단 함수인 delay에서 일시 중단 함수에서만 호출하라는 오류가 발생할 것이다. 오류가 발생하는 이유는 delay 함수는 코루틴이 일정 시간 동안 스레드를 양보하도록 만드는 함수여서 일시 중단 함수로 선언되었기 때문이다. 따라서 이 함수를 호출하는 곳도 일시 중단 함수여야 한다.

 

위의 함수에 아래와 같이 suspend 키워드를 추가해 주면 오류가 해결될 것이다.

suspend fun printHelloWorldDelay() {
    delay(100L)
    println("Hello World")
}

 

위의 함수를 main함수에 적용하면 아래와 같을 것이다.

fun main() = runBlocking<Unit> {
    printHelloWorldDelay()
    printHelloWorldDelay()
}

 

 

자 그렇다면 main 함수를 실행시키면 시간은 얼마나 걸릴까?

fun main() = runBlocking<Unit> {
    printHelloWorldDelay()
    printHelloWorldDelay()
}

suspend fun printHelloWorldDelay() {
    delay(100L)
    println("Hello World")
}

 

"suspend는 코루틴 아니야? 동시에 시작해서 동시에 끝나니까 그럼 100밀리초겠지"

아직 suspend의 진실에 대해 습득하지 않은 사람은 위와 같이 생각할 수 있다. 필자도 그랬다.

 

정답은 200 밀리초이다. 이유는 suspend 함수가 호출된다고 해서 새로운 코루틴이 생성되지 않기 때문에 100밀리 초를 대기하고 "Hello World"가 프린트되는 것이 하나의 코루틴에서 실행되기 때문이다.

 

만약 suspend 함수를 새로운 코루틴에서 실행시키고 싶은 거면 아래와 같이 suspend 함수를 launch나 async 같은 코루틴 빌더로 감싸야한다.

 

fun main() = runBlocking<Unit> {
    val job1 = launch {
       printHelloWorldDelay()
    }
    
    val job2 = launch {
       printHelloWorldDelay()
    }
    
    job1.join()
    job2.join()
}

suspend fun printHelloWorldDelay() {
    delay(100L)
    println("Hello World")
}​

 

이렇게 되면 각 일시중단 함수가 병렬로 실행돼 총 100밀리 초의 시간이 걸린다.

 

위와 같은 과정을 통해 suspend 호출했다고 해서 새로운 코루틴이 생성되는 것이 아니라는 사실을 알게 되었다.

 

 

맨 처음 다룬 코드를 다시 한번 살표 보자.

fun main() = runBlocking<Unit> {
    printHelloWorldDelay()
    printHelloWorldDelay()
}

suspend fun printHelloWorldDelay() {
    delay(100L)
    println("Hello World")
}

 

이 코드에서 printHelloWorldDelay의 함수가 suspend키워드 없이 fun으로 선언되면 오류가 발생했었다. 이유는 delay 함수가 일시 중단 함수였기 때문이다. 이렇듯 일시 중단 함수는 일시 중단 함수에서만 호출 가능하다는 것을 알게 됐을 것이다.

 

쉽게 정리하자면 일반 함수는 호출되면 처음부터 끝까지 한 번에 실행되며, 실행 중간에 멈출 수 있는 기능이 없다.

반면에 일시 중단 함수(suspend)는 실행 중간에 멈췄다가 나중에 재개할 수 있으며, 이런 특성은 비동기 작업에서 매우 유용하다.

코루틴은 일시 중단 함수를 실행할 수 있는 환경을 제공하며, 이를 통해 비동기 작업이나 멀티태스킹을 효율적으로 처리할 수 있도록 지원한다.