Coroutine

์ฝ”ํ‹€๋ฆฐ์˜ ์ฝ”๋ฃจํ‹ด(Coroutine)์€ ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ฐ„๊ฒฐํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด์˜ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ๊นŠ์ด ์žˆ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ์˜ ๋ณ€ํ™˜, JVM์—์„œ์˜ ์‹คํ–‰ ๋ฐฉ์‹, ์Šคํƒ ํ”„๋ ˆ์ž„ ๊ด€๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  ์šด์˜์ฒด์ œ์™€ CPU ์ˆ˜์ค€์—์„œ์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด์˜ ์ปดํŒŒ์ผ ๊ณผ์ •๊ณผ CPS ๋ณ€ํ™˜

์ฝ”๋ฃจํ‹ด์€ ์ปดํŒŒ์ผ ์‹œ์— Continuation-Passing Style(CPS)๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์„ ์ผ์ข…์˜ ์ƒํƒœ ๊ธฐ๊ณ„(state machine)๋กœ ๋ฐ”๊พธ๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

suspend ํ•จ์ˆ˜์˜ ๋ณ€ํ™˜

suspend ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜๋Š” ์ปดํŒŒ์ผ ์‹œ์— ์ถ”๊ฐ€์ ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ Continuation ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด Continuation ๊ฐ์ฒด๋Š” ์ฝ”๋ฃจํ‹ด์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์žฌ๊ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

suspend fun compute(value: Int): Int {
    return value * 2
}

์œ„์˜ compute ํ•จ์ˆ˜๋Š” ์ปดํŒŒ์ผ ์‹œ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

fun compute(value: Int, continuation: Continuation<Int>): Any {
    // ๋ณ€ํ™˜๋œ ์ฝ”๋“œ ๋‚ด์šฉ
}

์—ฌ๊ธฐ์„œ Any ํƒ€์ž…์€ ์ฝ”๋ฃจํ‹ด์ด ์ผ์‹œ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•œ ์ผ๋ฐ˜์ ์ธ ๋ฐ˜ํ™˜ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

์ƒํƒœ ๊ธฐ๊ณ„(State Machine)๋กœ์˜ ๋ณ€ํ™˜

์ฝ”๋ฃจํ‹ด์€ ์ผ์‹œ ์ค‘๋‹จ ์ง€์ ๋งˆ๋‹ค ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ƒํƒœ ๊ธฐ๊ณ„๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ฐ suspend ์ง€์ ์€ ์ƒํƒœ ๋ฒˆํ˜ธ๋กœ ํ‘œ์‹œ๋˜๋ฉฐ, ์ฝ”๋ฃจํ‹ด์ด ์žฌ๊ฐœ๋  ๋•Œ ํ•ด๋‹น ์ƒํƒœ๋ถ€ํ„ฐ ์‹คํ–‰์„ ์ด์–ด๊ฐ‘๋‹ˆ๋‹ค.

suspend fun exampleCoroutine() {
    val result1 = suspendFunction1()
    val result2 = suspendFunction2(result1)
    println(result2)
}

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ƒํƒœ ๊ธฐ๊ณ„๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๊ฐ suspend ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ƒํƒœ ๊ฐ์ฒด์˜ ์ƒ์„ฑ

์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ์ง€์—ญ ๋ณ€์ˆ˜, ํ˜„์žฌ ์‹คํ–‰ ์œ„์น˜, Continuation ๋“ฑ ์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

Continuation ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ฝ”๋ฃจํ‹ด ์ปจํ…์ŠคํŠธ

Continuation ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ฝ”๋ฃจํ‹ด์˜ ์žฌ๊ฐœ๋ฅผ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

interface Continuation<T> {
    val context: CoroutineContext
    fun resumeWith(result: Result<T>)
}
  • context: ์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰ ์ปจํ…์ŠคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋””์ŠคํŒจ์ฒ˜, ์žก(Job), ์ด๋ฆ„ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

  • resumeWith: ์ฝ”๋ฃจํ‹ด์„ ์žฌ๊ฐœํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋กœ, ๊ฒฐ๊ณผ ๋˜๋Š” ์˜ˆ์™ธ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

JVM์—์„œ์˜ ์ฝ”๋ฃจํ‹ด ์‹คํ–‰

์ฝ”๋ฃจํ‹ด์€ JVM ์ƒ์—์„œ ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€๋งŒ, ์ผ์‹œ ์ค‘๋‹จ ์ง€์ ์—์„œ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ณต์›ํ•˜๋Š” ์ถ”๊ฐ€์ ์ธ ๋กœ์ง์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

์Šคํƒ ํ”„๋ ˆ์ž„ ๋Œ€์‹  ํž™ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ

์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ํ˜ธ์ถœ ์Šคํƒ์— ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์ƒ์„ฑํ•˜์ง€๋งŒ, ์ฝ”๋ฃจํ‹ด์€ ์ผ์‹œ ์ค‘๋‹จ๊ณผ ์žฌ๊ฐœ๋ฅผ ์œ„ํ•ด ์‹คํ–‰ ์ƒํƒœ๋ฅผ ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋ฃจํ‹ด์ด ์Šค๋ ˆ๋“œ์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

suspend fun fetchData(): String {
    delay(1000)
    return "๋ฐ์ดํ„ฐ ์ˆ˜์‹  ์™„๋ฃŒ"
}

์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

fun fetchData(continuation: Continuation<String>): Any {
    val continuationImpl = object : ContinuationImpl(continuation) {
        var label = 0
        override fun invokeSuspend(result: Result<Any>): Any {
            when (label) {
                0 -> {
                    label = 1
                    if (delay(1000, this) == COROUTINE_SUSPENDED) {
                        return COROUTINE_SUSPENDED
                    }
                }
                1 -> {
                    return "๋ฐ์ดํ„ฐ ์ˆ˜์‹  ์™„๋ฃŒ"
                }
                else -> throw IllegalStateException("Unexpected label")
            }
        }
    }
    return continuationImpl.invokeSuspend(Result.success(Unit))
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์ฝ”๋ฃจํ‹ด์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ƒํƒœ ๊ธฐ๊ณ„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. label ๋ณ€์ˆ˜๋Š” ํ˜„์žฌ ์‹คํ–‰ ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, invokeSuspend ๋ฉ”์„œ๋“œ๋Š” ์ฝ”๋ฃจํ‹ด์ด ์žฌ๊ฐœ๋  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

์šด์˜์ฒด์ œ์™€ CPU ์ˆ˜์ค€์—์„œ์˜ ๋™์ž‘

์ฝ”๋ฃจํ‹ด์€ **์‚ฌ์šฉ์ž ๊ณต๊ฐ„(user-space)**์—์„œ ๋™์ž‘ํ•˜๋ฏ€๋กœ, ์šด์˜์ฒด์ œ์˜ ์Šค์ผ€์ค„๋Ÿฌ๋‚˜ CPU์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์— ์ง์ ‘์ ์ธ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ์™€ ์ฝ”๋ฃจํ‹ด์˜ ์ฐจ์ด์ 

  • ์Šค๋ ˆ๋“œ: ์šด์˜์ฒด์ œ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์‹คํ–‰ ๋‹จ์œ„๋กœ, ๊ฐ ์Šค๋ ˆ๋“œ๋Š” ๋…๋ฆฝ์ ์ธ ํ˜ธ์ถœ ์Šคํƒ๊ณผ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์€ ๋น„์šฉ์ด ๋†’์Šต๋‹ˆ๋‹ค.

  • ์ฝ”๋ฃจํ‹ด: ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ๊ด€๋ฆฌ๋˜๋Š” ๊ฒฝ๋Ÿ‰ ์‹คํ–‰ ๋‹จ์œ„๋กœ, ์Šค๋ ˆ๋“œ ๋‚ด์—์„œ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด ๊ฐ„์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์€ ์ƒํƒœ ๊ฐ์ฒด์˜ ์ „ํ™˜๋งŒ ํ•„์š”ํ•˜๋ฏ€๋กœ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ ์Šต๋‹ˆ๋‹ค.

๋””์ŠคํŒจ์ฒ˜์™€ ์Šค๋ ˆ๋“œ ํ’€

์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰์€ CoroutineDispatcher์— ์˜ํ•ด ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ๋””์ŠคํŒจ์ฒ˜๋Š” ์ฝ”๋ฃจํ‹ด์„ ์–ด๋Š ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Dispatchers.Default: ๊ณต์œ ๋œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Dispatchers.IO: I/O ์ž‘์—…์— ์ตœ์ ํ™”๋œ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Dispatchers.Main: ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด์˜ ์ผ์‹œ ์ค‘๋‹จ๊ณผ ์žฌ๊ฐœ ๊ณผ์ •

์ฝ”๋ฃจํ‹ด์˜ ์ผ์‹œ ์ค‘๋‹จ๊ณผ ์žฌ๊ฐœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

  1. ์ผ์‹œ ์ค‘๋‹จ ์ง€์  ๋„๋‹ฌ: suspend ํ•จ์ˆ˜๋‚˜ ์ผ์‹œ ์ค‘๋‹จ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‹œ ์ฝ”๋ฃจํ‹ด์€ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  COROUTINE_SUSPENDED๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  2. ์ƒํƒœ ์ €์žฅ: ์ฝ”๋ฃจํ‹ด์˜ ์ง€์—ญ ๋ณ€์ˆ˜์™€ ์‹คํ–‰ ์œ„์น˜ ๋“ฑ์ด ์ƒํƒœ ๊ฐ์ฒด์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

  3. ์žฌ๊ฐœ ์‹œ์ : ์ผ์‹œ ์ค‘๋‹จ๋œ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด, Continuation.resumeWith๋ฅผ ํ†ตํ•ด ์ฝ”๋ฃจํ‹ด์ด ์žฌ๊ฐœ๋ฉ๋‹ˆ๋‹ค.

  4. ์ƒํƒœ ๋ณต์›: ์ €์žฅ๋œ ์ƒํƒœ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

์ฝ”๋ฃจํ‹ด์˜ ์ƒํƒœ ๊ฐ์ฒด๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜๋ฏ€๋กœ, ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด์ด ์™„๋ฃŒ๋˜๊ฑฐ๋‚˜ ์ทจ์†Œ๋˜๋ฉด ๊ด€๋ จ๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ž๋™์œผ๋กœ ํšŒ์ˆ˜๋ฉ๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€

์ฝ”๋ฃจํ‹ด์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ฝ”๋ฃจํ‹ด์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ์ ์ ˆํžˆ ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ, ์ฝ”๋ฃจํ‹ด ๋‚ด๋ถ€์—์„œ ์ฐธ์กฐํ•˜๋Š” ์ž์›(์˜ˆ: ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ, ํŒŒ์ผ ๋“ฑ)์€ ํ•„์š”์— ๋”ฐ๋ผ ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด๊ณผ ์Šคํƒ ํ”„๋ ˆ์ž„

์ฝ”๋ฃจํ‹ด์€ ์ผ์‹œ ์ค‘๋‹จ ์‹œ ์Šคํƒ ํ”„๋ ˆ์ž„์„ ์œ ์ง€ํ•˜์ง€ ์•Š๊ณ  ํž™์— ์ €์žฅ๋œ ์ƒํƒœ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์‹คํ–‰ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋ฃจํ‹ด์ด ์Šค๋ ˆ๋“œ์— ์ข…์†๋˜์ง€ ์•Š๊ณ , ๋งŽ์€ ์ˆ˜์˜ ์ฝ”๋ฃจํ‹ด์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์‹œ: ์ƒํƒœ ๊ธฐ๊ณ„๋กœ์˜ ๋ณ€ํ™˜

๋‹ค์Œ์€ suspend ํ•จ์ˆ˜๊ฐ€ ์ƒํƒœ ๊ธฐ๊ณ„๋กœ ๋ณ€ํ™˜๋˜๋Š” ๊ณผ์ •์„ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

suspend fun simpleCoroutine() {
    println("์ฝ”๋ฃจํ‹ด ์‹œ์ž‘")
    delay(1000)
    println("์ฝ”๋ฃจํ‹ด ์žฌ๊ฐœ")
}

์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด ๋ณ€ํ™˜๋œ ์ฝ”๋“œ:

class SimpleCoroutine(continuation: Continuation<Unit>) : ContinuationImpl(continuation) {
    var label = 0
    override fun invokeSuspend(result: Result<Any?>): Any? {
        when (label) {
            0 -> {
                label = 1
                println("์ฝ”๋ฃจํ‹ด ์‹œ์ž‘")
                if (delay(1000, this) == COROUTINE_SUSPENDED) {
                    return COROUTINE_SUSPENDED
                }
            }
            1 -> {
                println("์ฝ”๋ฃจํ‹ด ์žฌ๊ฐœ")
                return Unit
            }
            else -> throw IllegalStateException("์ž˜๋ชป๋œ ์ƒํƒœ")
        }
    }
}

์—ฌ๊ธฐ์„œ label์€ ํ˜„์žฌ ์‹คํ–‰ ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์ฝ”๋ฃจํ‹ด์ด ์žฌ๊ฐœ๋  ๋•Œ ํ•ด๋‹น ์œ„์น˜๋ถ€ํ„ฐ ์‹คํ–‰์„ ์ด์–ด๊ฐ‘๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด์˜ ์„ฑ๋Šฅ ์ด์ 

์ฝ”๋ฃจํ‹ด์€ ์Šค๋ ˆ๋“œ์— ๋น„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ฑ๋Šฅ์ ์ธ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ๋‚ฎ์€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰: ์Šค๋ ˆ๋“œ๋ณด๋‹ค ํ›จ์”ฌ ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜๋งŽ์€ ์ฝ”๋ฃจํ‹ด์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋น ๋ฅธ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ: ์ฝ”๋ฃจํ‹ด ๊ฐ„์˜ ์ „ํ™˜์€ ํž™์— ์ €์žฅ๋œ ์ƒํƒœ ๊ฐ์ฒด๋งŒ ๊ต์ฒดํ•˜๋ฉด ๋˜๋ฏ€๋กœ ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

  • ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฐ„๊ฒฐํ•œ ํ‘œํ˜„: ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ๋กœ์ง์„ ๋™๊ธฐ ์ฝ”๋“œ์ฒ˜๋Ÿผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด๊ณผ JVM ๋ฐ”์ดํŠธ์ฝ”๋“œ

์ฝ”๋ฃจํ‹ด์ด ์ปดํŒŒ์ผ๋˜๋ฉด JVM ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋˜๋ฉฐ, ์ด๋Š” ์ผ๋ฐ˜์ ์ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ๊ณผ๋Š” ๋‹ค๋ฅธ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ฝ”๋ฃจํ‹ด์˜ ์ผ์‹œ ์ค‘๋‹จ ์ง€์ ์€ invokeSuspend ๋ฉ”์„œ๋“œ ๋‚ด์˜ ๋ถ„๊ธฐ๋ฌธ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ, ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ณ€์ˆ˜๋“ค์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

๋ฐ”์ดํŠธ์ฝ”๋“œ ๋ถ„์„

์ปดํŒŒ์ผ๋œ ์ฝ”๋ฃจํ‹ด์˜ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด L$0, L$1 ๋“ฑ์˜ ๋ณ€์ˆ˜๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋ฃจํ‹ด์˜ ์ง€์—ญ ๋ณ€์ˆ˜์™€ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ํ•„๋“œ์ž…๋‹ˆ๋‹ค.

public final class SimpleCoroutine extends ContinuationImpl {
    Object L$0;
    int label;

    public SimpleCoroutine(Continuation<?> continuation) {
        super(continuation);
    }

    @Override
    public final Object invokeSuspend(Object result) {
        switch (label) {
            case 0:
                // ์ฝ”๋ฃจํ‹ด ์‹œ์ž‘ ๋ถ€๋ถ„
                break;
            case 1:
                // ์ฝ”๋ฃจํ‹ด ์žฌ๊ฐœ ๋ถ€๋ถ„
                break;
            default:
                throw new IllegalStateException("์ž˜๋ชป๋œ ์ƒํƒœ");
        }
    }
}

์ฝ”๋ฃจํ‹ด์˜ ํ•œ๊ณ„์™€ ๊ณ ๋ ค ์‚ฌํ•ญ

  • ๋””๋ฒ„๊น…์˜ ๋ณต์žก์„ฑ: ์ฝ”๋ฃจํ‹ด์˜ ๋น„๋™๊ธฐ ์‹คํ–‰๊ณผ ์ƒํƒœ ๊ธฐ๊ณ„๋กœ์˜ ๋ณ€ํ™˜์œผ๋กœ ์ธํ•ด ๋””๋ฒ„๊น…์ด ๋ณต์žกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ์œ„ํ—˜: ์ฝ”๋ฃจํ‹ด์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ์ ์ ˆํžˆ ๊ด€๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์Šค๋ ˆ๋“œ ์ „ํ™˜ ๋น„์šฉ: ์ฝ”๋ฃจํ‹ด์ด ๋‹ค๋ฅธ ๋””์ŠคํŒจ์ฒ˜๋กœ ์ „ํ™˜๋˜๋ฉด ์Šค๋ ˆ๋“œ ์Šค์œ„์นญ์ด ๋ฐœ์ƒํ•˜์—ฌ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Last updated

Was this helpful?