[Coroutine] ์ฝ”๋ฃจํ‹ด ๋””์ŠคํŒจ์ฒ˜

๐Ÿ’ก RxJava์—์„œ์˜ ์Šค์ผ€์ค„๋Ÿฌ์™€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ์ฝ”๋ฃจํ‹ด ๋””์ŠคํŒจ์ฒ˜์— ๋Œ€ํ•˜์—ฌ ํ•™์Šตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

CoroutineDispatcher

  • ์ฝ”ํˆฌ๋ฆฐ ๋””์ŠคํŒจ์ฒ˜๋Š” ์ฝ”๋ฃจํ‹ด์„ ์Šค๋ ˆ๋“œ๋กœ ๋ณด๋‚ด๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋“  ์ž‘์—…์€ ์Šค๋ ˆ๋“œ ์œ„์—์„œ ์‹คํ–‰๋ผ์•ผ ํ•˜๊ณ , ์ฝ”๋ฃจํ‹ด ๋˜ํ•œ ์ž‘์ž…์ด๋ฏ€๋กœ ์Šค๋ ˆ๋“œ ์œ„์—์„œ๋งŒ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์šฐ๋ฆฌ๊ฐ€ ์ฝ”๋ฃจํ‹ด์„ ๋งŒ๋“ค์–ด CoroutineDispatcher๋กœ ์ฝ”๋ฃจํ‹ด ์‹คํ–‰์„ ์š”์ฒญํ•˜๋ฉด, CoroutineDispatcher๋Š” ์ž์‹ ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œํ’€์˜ ์Šค๋ ˆ๋“œ ์ค‘ ํ•˜๋‚˜์— ์ฝ”๋ฃจํ‹ด์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๋””์ŠคํŒจ์ฒ˜

  • ๋””์ŠคํŒจ์ฒ˜๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ Dispatchers.Default๊ฐ€ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
  • CPU๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ๋””์ŠคํŒจ์ฒ˜๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ปดํ“จํ„ฐ์˜ CPU ๊ฐœ์ˆ˜์™€ ๋™์ผํ•œ ์ˆ˜(์ตœ์†Œ 2๊ฐœ ์ด์ƒ)์˜ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
suspend fun main() = coroutineScope {
    repeat(1000) {
        launch { //**Dispatchers.Default**
            val threadName = Thread.currentThread().name
            println("Running on thread: $threadName")
        }
    }	****
}
// Running on thread: DefaultDispathcer-worker-1
// Running on thread: DefaultDispathcer-worker-2
// ....
  • runBlocking์€ ๋””์ŠคํŒจ์ฒ˜๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์œผ๋ฉด ์ž์‹ ๋งŒ์˜ ๋””์ŠคํŒจ์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ Dispatchers.Default๋ฅผ ์ž๋™์œผ๋กœ ์„ ํƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์œ„ ์—์„œ๋Š” coroutineScope ๋Œ€์‹ ์— runBlocking์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ์ฝ”๋ฃจํ‹ด์€ main์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋””์ŠคํŒจ์ฒ˜ ์ œํ•œํ•˜๊ธฐ

  • limitedParallelism์„ ์‚ฌ์šฉํ•ด์„œ ๋””์ŠคํŒจ์ฒ˜๊ฐ€ ๊ฐ™์€ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ฐ™์€ ์‹œ๊ฐ„์— ํŠน์ • ์ˆ˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
private val dispatcher = Dispatchers
    .Default
    .limitedParallelism(5)
  • limitedParallelism์€ kotlinx.coroutines 1.6 ๋ฒ„์ „์—์„œ ๋„์ž…๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์ธ ๋””์ŠคํŒจ์ฒ˜

  • Dispatchers.Main์„ ํ†ตํ•ด์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ฝ”๋ฃจํ‹ด์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • UI์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋˜๋ฉด ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฉˆ์ถ”๋ฏ€๋กœ, ์กฐ์‹ฌ์Šค๋Ÿฝ๊ฒŒ ๋‹ค๋ค„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์‹œ kotlinx-coroutines-test์—์„œ Dispatchers.setMain(dispatcher)๋กœ ๋””์ŠคํŒจ์ฒ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ธ”๋กœํ‚น ๋Œ€์‹  ์ค‘๋‹จํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ณต์žกํ•œ ์—ฐ์‚ฐ์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด Dispatchers.Main์œผ๋กœ ๊ธฐ๋ณธ ๋””์ŠคํŒจ์ฒ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

IO ๋””์ŠคํŒจ์ฒ˜

  • ๋””์Šคํฌ ๋˜๋Š” ๋„คํŠธ์›Œํฌ I/O ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š”๋ฐ ์ตœ์ ํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • IO ๋””์ŠคํŒจ์ฒ˜๋Š” ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ด๋‚˜ ๋ธ”๋กœํ‚น ํ•จ์ˆ˜๊ฐ€ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฉˆ์ถ”๊ฒŒ ํ•  ์ˆ˜๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜์ง€ ์•Š๊ณ , IO ๋””์ŠคํŒจ์ฒ˜๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
suspend fun main() {
    val time = measureTimeMillis {
        coroutineScope {
            repeat(50) {
                launch(Dispatchers.IO) {
                    Thread.sleep(1000)
                }
            }
        }
    }
    print(time) // ~ 1000
}
  • Dispathcers.Default์™€ Dispathcers.IO๋Š” ๊ฐ™์€ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.
    • ์Šค๋ ˆ๋“œ๋Š” ์žฌ์‚ฌ์šฉ๋˜๊ณ  ๋‹ค์‹œ ๋ฐฐ๋ถ„๋  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ, ๋…๋ฆฝ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋””์ŠคํŒจ์ฒ˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๊ณ ๊ฐˆ์‹œํ‚ค๋Š” ๊ฒฝ์šฐ๋Š” ์—†์Šต๋‹ˆ๋‹ค.
suspend fun main(): Unit = coroutineScope {
    launch(Dispatchers.Default){
        println(Thread.currentThread().name)
        withContext(Dispatchers.IO) {
            println(Thread.currentThead().name)
        }
    }
}
// DefaultDispatcher-worker-2
// DefaultDispatcher-worker-2
  • Dispatchers.IO์—์„œ 64๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊นŒ์ง€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , 8๊ฐœ์˜ ์ฝ”์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด ๊ณต์œ  ์Šค๋ ˆ๋“œ ํ’€์—์„œ ํ™œ์„ฑํ™”๋œ ์Šค๋ ˆ๋“œ๋Š” 72๊ฐœ ์ž…๋‹ˆ๋‹ค.

Dispatchers.IO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

  • ๊ฐ€์žฅ ํ”ํ•œ ๊ฒฝ์šฐ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ธ”๋กœํ‚น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ withContext(Dispatchers.IO)๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ์ค‘๋‹จํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.
withContext(Dispatchers.IO)
  • ๋ฐ˜๋ฉด์— withContext(Dispatchers.IO)๋กœ ๋ž˜ํ•‘ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ limitedParallelism์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค์Šคํ…€ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•˜๋Š” IO ๋””์ŠคํŒจ์ฒ˜

  • limitedParallelism๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋…์ง‘์ ์ธ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ฐ€์ง„ ์ƒˆ๋กœ์šด ๋””์ŠคํŒจ์ฒ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ํ’€์€ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋งŒํผ ๋งŽ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.(64๊ฐœ ์ด์ƒ ํ™œ์šฉ ๊ฐ€๋Šฅ)
    • 100๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Dispatchers.IO๋Š” ์ด 2์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. (64๊ฐœ ์ˆ˜ํ–‰ - 1์ดˆ, ๋‚˜๋จธ์ง€ 36๊ฐœ ์ˆ˜ํ–‰ - 1์ดˆ)
    • ๋ฐ˜๋ฉด์— limitedParallelism๋ฅผ ํ™œ์šฉํ•˜๋ฉด 100๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋กœ 1์ดˆ๋งŒ์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
launch {
    val dispatcher = Dispatchers.IO
        .limitedParalledlism(100)
}
  • Dispatchers.Default์˜ limitedParallelism์€ ๋””์ŠคํŒจ์ฒ˜์˜ ์Šค๋ ˆ๋“œ ์ˆ˜ ์ œํ•œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • Dispatchers.IO์˜ limitedParallelism์€ Dispatchers.Default์™€ ๋…๋ฆฝ์ ์ธ ๋””์ŠคํŒจ์ฒ˜๋ฅผ ๋งŒ๋“ค์ง€๋งŒ, ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฌด์ œํ•œ์ธ ์Šค๋ ˆ๋“œ ํ’€์„ ํ•จ๊ป˜ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

  • ํ•œ๋„๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์— ์ •๋‹ต์€ ์—†์ง€๋งŒ, ๋„ˆ๋ฌด ๋งŽ์€ ์Šค๋ ˆ๋“œ๋Š” ์ž์›์„ ๋น„ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์Šค๋ ˆ๋“œ ์ˆ˜๊ฐ€ ๋„ˆ๋ฌด ์ ๋‹ค๋ฉด ์„ฑ๋Šฅ์ƒ ์ข‹์ง€ ์•Š์œผ๋ฏ€๋กœ ์ ์ ˆํ•œ ๋ฐฐ์น˜๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ ๋””์ŠคํŒจ์ฒ˜ ํ™œ์šฉ

์ •ํ•ด์ง„ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ฐ€์ง„ ๋””์ŠคํŒจ์ฒ˜

  • ๋ช‡๋ช‡ ๊ฐœ๋ฐœ์ž๋“ค์€ ์ž์‹ ๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ์Šค๋ ˆ๋“œ ํ’€์„ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๊ธฐ ์›ํ•˜๋ฉฐ, ์ž๋ฐ”๋Š” ์ด๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ API๋ฅผ ์ œ๊ณตํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฐ˜๋ฉด์— ์ด๋Ÿฌํ•œ ๋””์ŠคํŒจ์ฒ˜๋Š” close ํ•จ์ˆ˜๋กœ ๋ฐ˜๋“œ์‹œ ๋‹ซ์•„์•ผ ํ•˜๋Š” ๋“ฑ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊นœ๋ฐ•ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์Šˆ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์Šค๋ ˆ๋“œ ๋ˆ„์ˆ˜๋ฅผ ์ผ์œผํ‚ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ฑ๊ธ€์Šค๋ ˆ๋“œ๋กœ ์ œํ•œ๋œ ๋””์ŠคํŒจ์ฒ˜

  • ๋‹ค์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๋””์ŠคํŒจ์ฒ˜๋Š” ๊ณต์œ  ์ƒํƒœ๋กœ ์ธํ•œ ๋ฌธ์ œ๋ฅผ ์ƒ๊ฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
var i = 0

suspend fun main(): Unit = coroutineScope {
    repeat(10_000) {
        launch(Dispatchers.IO) {
            i++
        }
    }
    delay(1000)
    println(i) // ~9930
}
  • i๋ฅผ 1์”ฉ ์ฆ๊ฐ€์‹œ์ผœ 10000์„ ๊ธฐ๋Œ€ํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์ด๋ณด๋‹ค ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ ์ด์œ ๋Š” ๋™์ผ ์‹œ๊ฐ„์— ๋‹ค์ˆ˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ  ์ƒํƒœ(i ํ”„๋กœํผํ‹ฐ)๋ฅผ ๋ณ€๊ฒฝํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์‹ฑ๊ธ€์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ€์ง„ ๋””์ŠคํŒจ์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
var i = 0

suspend fun main(): Unit = coroutineScope {
    val dispatcher = Dispatchers.Default
        .limitedParalledlism(1)

    repeat(10_000) {
        launch(dispatcher) {
            i++
        }
    }
    delay(1000)
    println(i) // 10000
}
  • ํ•˜์ง€๋งŒ ๋‹จ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋˜๋ฉด ์ž‘์—…์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ๋‹จ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ œํ•œ๋ฐ›์ง€ ์•Š๋Š” ๋””์ŠคํŒจ์ฒ˜

  • Dispatchers.Unconfined๋ฅผ ํ™œ์šฉํ•ด ์ œํ•œ๋ฐ›์ง€ ์•Š๋Š” ๋””์ŠคํŒจ์ฒ˜๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ˜ธ์ถœ ์Šค๋ ˆ๋“œ์—์„œ ์ฝ”๋ฃจํ‹ด์„ ์‹œ์ž‘ํ•˜์ง€๋งŒ ์ด๋Š” ์ฒซ๋ฒˆ์งธ ์ค‘๋‹จ์ ์„ ๋งŒ๋‚ ๋•Œ ๊นŒ์ง€๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ์ค‘๋‹จ์  ์ดํ›„ ์ฝ”๋ฃจํ‹ด์ด ์žฌ๊ฐœ๋  ๋•Œ๋Š” ์ค‘๋‹จ ํ•จ์ˆ˜๋ฅผ ์žฌ๊ฐœํ•œ ์Šค๋ ˆ๋“œ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ์ฝ”๋ฃจํ‹ด์ด CPU ์‹œ๊ฐ„์„ ์†Œ๋ชจํ•˜์ง€ ์•Š๊ฑฐ๋‚˜, ๊ณต์œ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ํŠน์ • ์Šค๋ ˆ๋“œ์— ๊ตญํ•œ๋œ ์ž‘์—…์ด ์•„๋‹Œ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์— ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • launch๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒฝ์šฐ ์‹œ๊ฐ„์„ ๋™๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์ธ ๋””์ŠคํŒจ์ฒ˜๋กœ ์ฆ‰์‹œ ์˜ฎ๊ธฐ๊ธฐ

  • ์ฝ”๋ฃจํ‹ด์„ ๋ฐฐ์ •ํ•˜๋Š” ๊ฒƒ์—๋„ ๋น„์šฉ์ด ๋“ค๋ฉฐ, withContext๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์ฝ”๋ฃจํ‹ด์€ ์ค‘๋‹จ๋˜๊ณ  ํ์—์„œ ๊ธฐ๋‹ค๋ฆฌ๋‹ค๊ฐ€ ์žฌ๊ฐœ๋ฉ๋‹ˆ๋‹ค.
  • ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฏธ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ฝ”๋ฃจํ‹ด์„ ๋‹ค์‹œ ๋ฐฐ์ •ํ•˜๋ฉด ์ž‘์ง€๋งŒ ํ•„์š” ์—†๋Š” ๋น„์šฉ์ด ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
suspend fun showUser(user: User) =
    withContext(Dispatchers.Main.immediate) {
        userNameElement.text = user.name
    }
  • Dispatchers.Main.immediate๋ฅผ ํ™œ์šฉํ•ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ฐฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์•ฝ

  • ๋””์ŠคํŒจ์ฒ˜๋Š” ์ฝ”๋ฃจํ‹ด์ด ์‹คํ–‰๋  ์Šค๋ ˆ๋“œ๋‚˜ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • Dispatchers.Default๋Š” CPU ์ง‘์•ฝ์ ์ธ ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Dispatchers.Main์€ Android, Swing, JavaFX์—์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์— ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Dispatchers.Main.immediate๋Š” Dispatchers.Main์ด ์‚ฌ์šฉํ•˜๋Š” ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜์ง€๋งŒ ๊ผญ ํ•„์š”ํ•  ๋•Œ๋งŒ ์žฌ๋ฐฐ์ •๋ฉ๋‹ˆ๋‹ค.
  • Dispatchers.IO๋Š” ๋ธ”๋กœํ‚น ์—ฐ์‚ฐ์„ ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Dispatchers.Unconfined๋Š” ์ฝ”๋ฃจํ‹ด์ด ์‹คํ–‰๋  ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•ด์„œ ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ 

https://medium.com/@sahilthakar10/dispatchers-io-and-default-under-the-hood-b39aee24d2e9