우테코 8기/Kotlin

Kotlin coroutine - suspend 함수

Reddish 2026. 9. 5. 22:36
반응형

suspend 함수


코루틴 실행을 일시정지 할 수 있는 함수이다. 대표적으로 delay 함수가 지정한 시간만큼 코루틴을 일시정지 하는 함수이다. (delay가 사실 suspend 함수 종류중 하나이다.)

코루틴 라이브러리에서는 delay 뿐만 아니라 다양한 suspend 함수를 지원한다.

  • suspend 함수는 코루틴 또는 다른 suspend 함수에서만 호출해야한다

 

예시


우리는 1초가 걸리는 A 작업과 B 작업을 하고싶다. A 와 B는 시간이 많이 걸리는 작업이므로, 다른 코루틴에게 맡겨놓고 다른 작업을 처리하고자 한다.

대략적인 순서는 아래와 같다.

오래 걸리는 A와 B 작업을 먼저 실행시켜 놓는다. 다른 코루틴에게 해당 작업을 시켜놓고, 나는 다른 작업을 실행한다. 이를 코드로 표현하면 아래와 같다.

fun main() = runBlocking {
    launch {
        println("launch A Start")
        delay(1000L)
        println("launch A End")
    }
    launch {
        println("launch B Start")
        delay(1000L)
        println("launch B End")
    }
    delay(500L)
    println("Hello World!")
}

이 코드를 간단하게 리팩토링 해보자.

fun main() = runBlocking {
    launch {
        launchA()
    }
    launch { 
        launchB()
    }
		
    delay(500L)
    println("Hello World!")
}

fun launchA() {
    launch {
        println("launch A Start")
        delay(1000L)
        println("launch A End")
    }
}

fun launchB() {
    launch {
        println("launch B Start")
        delay(1000L)
        println("launch B End")
    }
}

이렇게 분리해도 되지 않을까?

위의 코드를 작성하면 에러가 발생한다. suspend함수 ‘delay’는 코루틴 또는 다른 suspend 내에서만 호출해야한다는 뜻이다. 이 말에서 delay라는 말을 제거하면 좀 더 범용적인 표현이 되는데, 다른 suspend 함수에서도 해당하기 때문이다.

suspend 함수는 코루틴 또는 다른 suspend 함수에서만 호출해야한다.

그러면 우리는 위 코드를 쉽게 고칠 수 있을 것이다.

suspend fun launchA() {
    launch {
        println("launch A Start")
        delay(1000L)
        println("launch A End")
    }
}

suspend fun launchB() {
    launch {
        println("launch B Start")
        delay(1000L)
        println("launch B End")
    }
}

이번에도 에러가 뜬다. 'launch' can not be called without the corresponding coroutine scope. Consider wrapping 'launch' in 'coroutineScope { }', using 'runBlocking { }', or using some other 'CoroutineScope'. 라고 한다.

코루틴은 특정 스레드에 종속되지 않고 일시 정지를 통해 동시성을 제공한다고 했다. 이 동시성은 비동기적 동작을 통해서 이뤄진다. delay를 했을 때 하나의 코루틴을 일시 정지해 가용 가능한 스레드 자원을 다른 코루틴에게 할당해 비동기적으로 동작하게 된다.

에러 메세지를 보면 launch 함수를 runBlocking 을 사용하거나, coroutineScope { } 로 감싸라고 한다. 그러면 둘 중 뭔갈 선택하겠지만, 나는 coroutineScope로 감싸겠다.

suspend fun launchA() = coroutineScope {
    launch {
        println("launch A Start")
        delay(1000L)
        println("launch A End")
    }
}

suspend fun launchB() = coroutineScope {
    launch {
        println("launch B Start")
        delay(1000L)
        println("launch B End")
    }
}

해당 내용을 이해하려면 코루틴 빌더에 대해서 알아야 하므로, 대략적으로 넘긴다. 알아야 할 사실은 코루틴 빌더는 CoroutineScope 내부에 선언되어야 한다는 점이고, launch 또한 코루틴 빌더라는 것이다. 그리고 코루틴 빌더 내부 역시 코루틴 스코프이다.

suspend 함수는 결국 코루틴 스코프 내에서 실행되어야 한다. suspend 함수는 코루틴을 일시정지 할 수 있는 함수이기 때문이다. 이는 재개할 수 있음을 의미한다. 각 함수가 delay()를 통해 일시정지를 했을 때 작업들이 종료되지 않고 지정한 시간 후 재개되어 결과값을 반환하는 것을 확인했다.

이는 suspend function이 코루틴이라는 것은 아니라는 것을 의미한다. suspend function을 호출한다고 새로운 코루틴이 형성되지 않는다. 결국 코루틴 빌더인 launch나 async와 같은 코루틴 빌더로 감싸야 함을 의미한다.

fun main() = runBlocking {
	launchA()
	launchB()
		
	delay(500L)
	println("Hello World!")
}

suspend fun launchA() = coroutineScope {
	launch {
		println("launch A Start")
		delay(1000L)
		println("launch A End")
	}
}

suspend fun launchB() = coroutineScope {
	launch {
		println("launch B Start")
		delay(1000L)
		println("launch B End")
	}
}
반응형

'우테코 8기 > Kotlin' 카테고리의 다른 글

Flow, StateFlow, SharedFlow  (0) 2026.10.04
Kotlin Annotation Retention  (0) 2026.09.20
expect / actual 키워드 (Kotlin Multiplatform, KMP)  (0) 2026.08.17
가변성을 제한하라  (0) 2026.07.19
Annotation과 Annotation Target  (2) 2026.06.03