코루틴은 일시 중단과 재개가 가능한 함수
코틀린에서는 일시 중단을 suspend 라는 키워드로 표현합니다.
suspend는 이 함수는 중단(suspend)될 수 있다는 의미이죠
즉, 함수가 실행 도중 잠시 멈췄다가 나중에 이어서 다시 실행될 수 있음을 나타냅니다.
이런 함수는 코루틴 안에서만 호출할 수 있습니다.
suspend fun fetchUserData(): User {
delay(1000) // 1초 일시 중단 (non-blocking)
return User("jaemin")
}
여기서 delay(1000)은 현재 실행 중인 스레드를 막지 않고 (코루틴을 실행하고 있던 스레드를 블로킹하지 않고) 1초 동안 코루틴만 일시 중단합니다.
이게 코루틴의 핵심 장점이죠 — 효율적이고 가벼운 비동기 처리.
suspend 함수는 코루틴 컨텍스트 안에서만 실행 가능합니다. 즉, 코루틴 블록 안에서만 호출 가능하죠
일반 함수는 실행을 시작하면 → 끝날 때까지 쭉 실행됨. → 중간에 멈추거나 재개하는 기능 없음
suspend 함수는 실행 중 “중단"했다가 “재개"할 수 있음 → 이게 코루틴의 핵심 기능
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
println("🕒 코루틴 A: 작업 시작")
delay(2000) // 여기서 중단됨 (2초 동안 멈춤)
println("✅ 코루틴 A: 작업 완료")
}
launch {
println("💡 코루틴 B: 작업 시작")
repeat(5) { i ->
println("💡 코루틴 B: $i")
delay(400) // 반복하면서 작업함
}
println("💡 코루틴 B: 작업 완료")
}
}
1 → 2 → 3 한 번에 실행됨. 멈추거나 나중에 이어서 실행 못함
suspend 함수 (코루틴) 중간에 멈출 수 있음
suspend fun helloSuspend() {
println("1")
delay(1000) // 💡 여기서 중단됨! (다른 일 가능)
println("2") // 💡 1초 후에 여기서 다시 이어서 실행
}
왜 일반 함수는 중단/재개 안 되나?
일반 함수는 JVM 바이트코드 수준에서 스택 기반으로 한 번에 실행되도록 설계됨.
반면 suspend 함수는 컴파일 시 내부적으로 Continuation이라는 상태 저장 구조로 변환됨. 즉, **“지금 어디까지 실행했는지 기억하는 설계”**가 적용되는 것.
launch {
println("🅰️ A 시작")
delay(2000) // ← 여기서 코루틴 A는 "suspend" = 대기 상태로 빠짐
println("🅰️ A 끝")
}
launch {
repeat(5) {
println("🅱️ B: $it")
delay(400) // ← 이것도 suspend 지점
}
}
결과:
🅰️ A 시작: 1747879622324
🅱️ B: 0 at 1747879622329
🅱️ B: 1 at 1747879622735
🅱️ B: 2 at 1747879623140
🅱️ B: 3 at 1747879623545
🅱️ B: 4 at 1747879623947
🅰️ A 끝: 1747879624333
🅱️ B: 5 at 1747879624351
🅱️ B: 6 at 1747879624755
🅱️ B: 7 at 1747879625160
🅱️ B: 8 at 1747879625565
🅱️ B: 9 at 1747879625970
실행 흐름:
A는 0ms에 시작해서 → delay(2000) → 2000ms쯤에 다시 실행될 준비 완료
B는 0ms부터 시작해서 → 400ms 간격으로 반복
2000ms쯤 되면 B는 5번째나 6번째 반복 중일 텐데
그 타이밍에 스레드가 A를 재개할 틈이 생기면, A가 다시 실행됩니다
이게 가능한 이유:
코루틴은 항상 suspend → resume을 반복
스레드가 놀지 않고 실행 가능한 코루틴에게 계속 작업을 넘김
시간 순서가 충족되면 → A가 우선순위 없이도 재개됨
결론:
코루틴은 일시 중단(suspend)과 재개(resume)가 가능한 함수로, 비동기 코드를 동기 코드처럼 쉽게 작성하게 해준다