[Coroutine] ์ฝ”๋ฃจํ‹ด ๋นŒ๋”

 ๐Ÿ’ก ์ฝ”๋ฃจํ‹ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋Š” kotlin.coroutines์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ฝ”๋ฃจํ‹ด ๋นŒ๋”์— ๋Œ€ํ•˜์—ฌ ํ•™์Šตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋ฃจํ‹ด ๋นŒ๋”

  • ์ค‘๋‹จ ํ•จ์ˆ˜๋Š” ์ปจํ‹ฐ๋‰ด์—์ด์…˜ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ฆ‰ ์ค‘๋‹จ ํ•จ์ˆ˜ → ์ผ๋ฐ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ผ๋ฐ˜ ํ•จ์ˆ˜ → ์ค‘๋‹จ ํ•จ์ˆ˜ ํ˜ธ์ถœ์€ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ์ค‘๋‹จ ํ•จ์ˆ˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ค‘๋‹จ ํ•จ์ˆ˜์— ์˜ํ•ด ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ์•ž์„œ ํ˜ธ์ถœํ•œ ์ค‘๋‹จ ํ•จ์ˆ˜ ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.
  • ์ค‘๋‹จ ํ•จ์ˆ˜๋ฅผ ์—ฐ์†์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด ์‹œ์ž‘๋˜๋Š” ์ง€์ ์ด ๋ฐ˜๋“œ์‹œ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฝ”๋ฃจํ‹ด ๋นŒ๋”(coroutine builder)๊ฐ€ ๊ทธ ์—ญํ• ์„ ํ•˜๋ฉฐ, ์ผ๋ฐ˜ ํ•จ์ˆ˜์™€ ์ค‘๋‹จ ๊ฐ€๋Šฅํ•œ ์„ธ๊ณ„๋ฅผ ์—ฐ๊ฒฐ์‹œํ‚ค๋Š” ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • launch
    • runBlocking
    • async

launch ๋นŒ๋”

  • launch๋Š” thread ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋ฉฐ, ๋ถˆ๊ฝƒ๋†€์ด๋ฅผ ํ•  ๋•Œ ๋ถˆ๊ฝƒ์ด ํ•˜๋Š˜ ์œ„๋กœ ๊ฐ์ž ํผ์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณ„๊ฐœ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
fun main() {
    GlobalScope.launch {
        delay(1000L)
        println("launch!")
    }
    GlobalScope.launch {
        delay(1000L)
        println("launch!")
    }
    GlobalScope.launch {
        delay(1000L)
        println("launch!")
    }
    println("load")
    Thread.sleep(2000L)
}
//load
// 1000L(1์ดˆ) ํ›„..
//launch!
//launch!
//launch!
  • ์œ„ ๋ฐฉ์‹์€ ์•ˆ๋“œ๋กœ์ด๋“œ๋‚˜ ๋ฐฑ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐฉ์‹์—์„œ ์ข‹์€ ๋ฐฉ์‹์ด ์•„๋‹ˆ์ง€๋งŒ, ์ฝ”๋ฃจํ‹ด ๋นŒ๋”์— ์˜ํ•ด ์‹œ์ž‘๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
    • ์‹ค์ œ ํ˜‘์—…์—์„œ๋Š” GlobalScope์˜ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฝ”ํ‹€๋ฆฐ ์–ธ์–ด๊ฐ€ ๋นŒ๋”๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Thread.sleep(2000L)์„ ์ค€ ์ด์œ ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • ์Šค๋ ˆ๋“œ๋ฅผ ์ž ๋“ค๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฉ”์ธ ํ•จ์ˆ˜๋Š” ์ฝ”๋ฃจํ‹ด์„ ์‹คํ–‰ํ•˜์ž๋งˆ์ž ๋๋‚˜๋ฒ„๋ฆฌ๋ฉฐ, ์ฝ”๋ฃจํ‹ด์ด ์ผ์„ ํ•  ๊ธฐํšŒ๋ฅผ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • delay(1000L)์€ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋ก์‹œํ‚ค์ง€ ์•Š๊ณ , ์ฝ”๋ฃจํ‹ด์„ ๋ธ”๋ก์‹œํ‚ต๋‹ˆ๋‹ค.

CoroutineScope

  • launch ํ•จ์ˆ˜๋Š” CoroutineScope ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ™•์žฅ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
  • CoroutineScope ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ถ€๋ชจ ์ฝ”๋ฃจํ‹ด๊ณผ ์ž์‹ ์ฝ”๋ฃจํ‹ด ์‚ฌ์ด์˜ ๊ด€๊ณ„ ์ •๋ฆฝ์„ ์œ„ํ•œ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ(structued concurrency)์„ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    • ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๋” ์•ˆ์ „ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๋””์ž์ธ ํŒจํ„ด
    • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ ๋™์‹œ์„ฑ์„ ๋‹ค๋ฃธ
    • ๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์œ„ ์ฝ”๋“œ์˜ Thred.sleep ์—†์ด ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์Œ

launch๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹

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

runBlocking ๋นŒ๋”

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

runBlocking ๋™์ž‘ ๋ฐฉ์‹

  • runBloking ๋‚ด๋ถ€์—์„œ delay(1000L)์„ ํ˜ธ์ถœํ•˜๋ฉด Thread.sleep(1000L)๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
fun main() {
    runBlocking {
        delay(1000L)
        println("load")
    }
    runBlocking {
        delay(1000L)
        println("load")
    }
    println("end")
}
// (1์ดˆ ํ›„_)
// load
// (1์ดˆ ํ›„_)
// load
// end

fun main() {
    Thread.sleep(1000L)
    println("load")
    Thread.sleep(1000L)
    println("load")
    println("end")
}
// (1์ดˆ ํ›„_)
// load
// (1์ดˆ ํ›„_)
// load
// end

runBlocking์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

  • ํ”„๋กœ๊ทธ๋žจ์ด ๋๋‚˜๋Š” ๊ฑธ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๋ฉ”์ธ ํ•จ์ˆ˜
  • ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ์œ ๋‹› ํ…Œ์ŠคํŠธ

async ๋นŒ๋”

  • async ๋นŒ๋”๋Š” launch์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๊ฐ’์„ ์ƒ์„ฑํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋žŒ๋‹ค ํ‘œํ˜„์‹์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•˜๋ฉฐ Deferred<T> ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉฐ, ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ค‘๋‹จ ๋ฉ”์„œ๋“œ์ธ await๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

async ๋นŒ๋”์˜ ํŠน์ง•

  • launch ๋นŒ๋”์™€ ๋น„์Šทํ•˜๋ฉฐ, ํ˜ธ์ถœ๋˜์ž๋งˆ์ž ์ฝ”๋ฃจํ‹ด์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ช‡ ๊ฐœ์˜ ์ž‘์—…์„ ํ•œ๋ฒˆ์— ์‹œ์ž‘ํ•˜๊ณ  ๋ชจ๋“  ๊ฒฐ๊ณผ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๊ธฐ๋‹ค๋ฆด ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Deferred๋Š” ๊ฐ’์ด ์ƒ์„ฑ๋˜๋ฉด ํ•ด๋‹น ๊ฐ’์„ ๋‚ด๋ถ€์— ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— await์—์„œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๋Š” ์ฆ‰์‹œ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ’์ด ์ƒ์„ฑ๋˜๊ธฐ ์ „์— await๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ๊ฐ’์ด ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
fun main() = runBlocking {
    val res1 = GlobalScope.async {
        delay(1000L)
        "Text 1"
    }
    val res1 = GlobalScope.async {
        delay(3000L)
        "Text 2"
    }
    val res1 = GlobalScope.async {
        delay(2000L)
        "Text 3"
    }
    println(res1.await())
    println(res2.await())
    println(res3.await())
    // (1์ดˆ ํ›„)
    // Text1
    // (2์ดˆ ํ›„)
    // Text2
    // Text3
}
  • async ๋นŒ๋”๋Š” launch์™€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ๋น„์Šทํ•˜์ง€๋งŒ, ๊ฐ’์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋งŒ ํ™œ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์–ด์™€ ํ•ฉ์น˜๋Š” ๊ฒฝ์šฐ์ฒ˜๋Ÿผ, ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ๋•Œ ์ฃผ๋กœ ํ™œ์šฉํ•œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
scope.launch {
    val news = async {
        newsRepo.getNews()
            .sortedByDescending { it.date }
    }
    val newsSummary = newsRepo.getNewsSummary()
    view.showNews(
        newsSummary,
        news.await()
}

๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ

  • ์ฝ”๋ฃจํ‹ด์ด GlobalScope์—์„œ ์‹œ์ž‘๋˜์—ˆ๋‹ค๋ฉด ํ”„๋กœ๊ทธ๋žจ์€ ํ•ด๋‹น ์ฝ”๋ฃจํ‹ด์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ฝ”๋ฃจํ‹ด์€ ์–ด๋–ค ์Šค๋ ˆ๋“œ๋„ ๋ธ”๋กํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ๊ทธ๋žจ์ด ๋๋‚˜๋Š” ๊ฑธ ๋ง‰์„ ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.
fun main() = runBlocking {
    GlobalScope.launch {
        delay(1000L)
        println("World!")
    }
    GlobalScope.launch {
        delay(2000L)
        println("World!")
    }
    println("Hello,")
}
// Hello,
  • launch์™€ async๋Š” CoroutineScope์˜ ํ™•์žฅํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์—, GlobalScope๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • block ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ฆฌ์‹œ๋ฒ„ ํƒ€์ž…์ด CoroutineScope์ธ ํ•จ์ˆ˜ํ˜• ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ๋Œ€์ฒดํ•  ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
fun <T> runBlocking(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job

fun <T> CoroutineScope.async(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Deferred<T>
  • ๋ชจ๋“  ์ฝ”๋ฃจํ‹ด ๋นŒ๋”๊ฐ€ CoroutineScope๋ฅผ ๋ฆฌ์‹œ๋ฒ„๋กœ ๋ฐ›๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด ์ด์œ ๋กœ GlobalScope๋ฅผ ๊ตณ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  this.launch๋ฅผ ํ†ตํ•ด์„œ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ด ๊ธฐ๋Šฅ์„ ํ†ตํ•ด์„œ launch๋Š” runBlocking์˜ ์ž์‹์ด ๋ฉ๋‹ˆ๋‹ค.
    • ๋ถ€๋ชจ๊ฐ€ ์ž์‹์„ ๊ธฐ๋‹ค๋ฆฌ๋ฏ€๋กœ, runBlocking์€ ์ž์‹์˜ ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
fun main() = runBlocking {
    this.launch {
        delay(1000L)
        println("World!")
    }
    println("Hello,")
}
// Hello,
// (1์ดˆ ํ›„)
// World!
  • ๋ถ€๋ชจ๋Š” ์ž์‹๋“ค์„ ์œ„ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์ž์‹๋“ค์€ ํ•ด๋‹น ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ์ด๋ผ๋Š” ๊ด€๊ณ„๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐํ™”๋œ ๋™์‹œ์„ฑ์˜ ํŠน์ง•

  • ์ž์‹์€ ๋ถ€๋ชจ ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค.
    • ์ž์‹์ด ๋ถ€๋ชจ ์ปจํ…์ŠคํŠธ๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ถ€๋ชจ๋Š” ๋ชจ๋“  ์ž์‹์ด ์ž‘์—…์„ ๋งˆ์น  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค
  • ๋ถ€๋ชจ ์ฝ”๋ฃจํ‹ด์ด ์ทจ์†Œ๋˜๋ฉด ์ž์‹๋„ ์ทจ์†Œ๋ฉ๋‹ˆ๋‹ค.
  • ์ž์‹ ์ฝ”๋ฃจํ‹ด์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ถ€๋ชจ ์ฝ”๋ฃจํ‹ด๋„ ์—๋Ÿฌ๋กœ ์†Œ๋ฉธํ•ฉ๋‹ˆ๋‹ค.

runBlocking์€?

  • ์ฝ”๋ฃจํ‹ด ๋นŒ๋” ์ค‘์— runBlocking์€ CoroutineScope์˜ ํ™•์žฅํ•จ์ˆ˜๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.
  • ์ด๋Š” runBlocking์€ ์ž์‹์ด ๋  ์ˆ˜ ์—†์œผ๋ฉฐ, ๋ฃจํŠธ ์ฝ”๋ฃจํ‹ด์œผ๋กœ๋งŒ ํ™œ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    • ๊ณ„์ธต์ƒ ๋ชจ๋“  ์ž์‹์˜ ๋ถ€๋ชจ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

ํ˜„์—…์—์„œ์˜ ์ฝ”๋ฃจํ‹ด ์‚ฌ์šฉ

  • ์ค‘๋‹จ ํ•จ์ˆ˜๋Š” ๋‹ค๋ฅธ ์ค‘๋‹จ ํ•จ์ˆ˜๋“ค๋กœ๋ถ€ํ„ฐ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•˜๋ฉฐ, ๋ชจ๋“  ์ค‘๋‹จ ํ•จ์ˆ˜๋Š” ์ฝ”๋ฃจํ‹ด ๋นŒ๋”๋กœ ์‹œ์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ๋˜ํ•œ runBlocking์„ ์ œ์™ธํ•œ ๋ชจ๋“  ์ฝ”๋ฃจํ‹ด ๋นŒ๋”๋Š” CoroutineScope์—์„œ ์‹œ์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ค‘๋‹จ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ํ•จ์ˆ˜ ๋‚ด์—๋Š” ์Šค์ฝ”ํ”„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ์Šค์ฝ”ํ”„๋ฅผ ์ธ์ž๋กœ ๋„˜๊ธฐ๋Š” ๊ฑด ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ฝ”๋ฃจํ‹ด ๋นŒ๋”๊ฐ€ ์‚ฌ์šฉํ•  ์Šค์ฝ”ํ”„๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์ค‘๋‹จ ํ•จ์ˆ˜์ธ coroutineScope ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์Šต๋‹ˆ๋‹ค.

scope๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•

  • runBlocking ํ™œ์šฉ
  • ์ง์ ‘ ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„ ์ œ์ž‘
  • ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ์Šค์ฝ”ํ”„ ์‚ฌ์šฉ
    • ๋ฐฑ์—”๋“œ : Ktor
    • ์•ˆ๋“œ๋กœ์ด๋“œ : Android KTX

coroutineScope ์‚ฌ์šฉํ•˜๊ธฐ

  • ์•„๋ž˜์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋‘ ๊ฐœ์˜ ์ž์›์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ
    • ๊ธ€ ๋ชฉ๋ก
suspend fun getArticlesForUser(
    userToken: String?,
): List<ArticleJson> = coroutineScope {
    val articles = async { articleRepository.getArticles() }
    val user = userService.getUser(userToken)
    articles.await()
        .filter { canSeeOnList(user, it) }
        .map { toArticleJson(it) }
}
  • coroutineScope๋Š” ๋žŒ๋‹ค ํ‘œํ˜„์‹์ด ํ•„์š”๋กœ ํ•˜๋Š” ์Šค์ฝ”ํ”„๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ์ค‘๋‹ด ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค.
  • let, run, use ๋˜๋Š” runBlocking ์ฒ˜๋Ÿผ ๋žŒ๋‹ค์‹์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋ฉด ๋ฌด์—‡์ด๋“  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ค‘๋‹จ ํ•จ์ˆ˜ ๋ฐ–์—์„œ ์Šค์ฝ”ํ”„๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด coroutineScope๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋ฉฐ, runBlocking์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์•ฝ

  • ๋™์‹œ์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•จ์ˆ˜๋ฅผ coroutineScope๋กœ ๋ž˜ํ•‘ํ•œ ๋‹ค์Œ, ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ๊ฒƒ์€ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ๋นŒ๋”๋ฅผ ํ˜ธ์ถœํ•จ์œผ๋กœ์จ ์‹œ์ž‘๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์Šค์ฝ”ํ”„๋Š” ํ•œ ๋ฒˆ ์ •์˜๋˜๋ฉด ๋‹ค์‹œ ์„ ์–ธํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ, ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์˜ˆ์™ธ์ฒ˜๋ฆฌ์— ์ต์ˆ™ํ•ด์ง€๋Š” ๋ฐฉ๋ฒ•๋„ ํ•™์Šต์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค !

https://m.yes24.com/Goods/Detail/123034354

 

์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด - ์˜ˆ์Šค24

์ฝ”ํ‹€๋ฆฐ ์ „๋ฌธ ๊ฐ•์‚ฌ๊ฐ€ ์•Œ๋ ค ์ฃผ๋Š” ์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด์— ๋Œ€ํ•œ ๋ชจ๋“  ๊ฒƒ!์ฝ”ํ‹€๋ฆฐ ์ฝ”๋ฃจํ‹ด์€ ํšจ์œจ์ ์ด๊ณ  ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ์–ด ์ž๋ฐ” ๊ฐ€์ƒ ๋จธ์‹ (JVM), ํŠนํžˆ ์•ˆ๋“œ๋กœ

m.yes24.com