๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

[Android : kotlin] flow ๊ฐœ๋… ์ดํ•ดํ•˜๊ธฐ

by hyeonha 2024. 7. 5.

๋ชฉ์ฐจ

    flow๋ž€?

     suspend function์€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋‹จ์ผ ๊ฐ’์„ ๋ฆฌํ„ดํ•œ๋‹ค.

    ๐Ÿค”๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๊ณ  ์‹ถ์œผ๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜์ง€? 

     

    ์ด ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด flow์ด๋‹ค.

    flow๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ณ„์‚ฐ๋œ ์—ฌ๋Ÿฌ ๊ฐ’๋“ค์„ ๋ฆฌํ„ดํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰ flow๋Š” ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

     

    flow์˜ emit

    emit์€ Flow์— ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. 

    flow ์ƒ์„ฑ์ž ๋‚ด๋ถ€์—์„œ emit ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฉ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

    flow์˜ collect

    collect์€ ์•ž์„œ emit์„ ํ†ตํ•ด flow์—์„œ ๋ฐฉ์ถœ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

    flow๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์—์„œ collect ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Flow๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ์ฆ‰ emit์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐฉ์ถœํ•˜๊ณ , collect๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๊ฒƒ์ด flow์˜ ๋™์ž‘ ํ๋ฆ„์ด๋‹ค.

     

    https://kotlinlang.org/docs/flow.html

     

    Asynchronous Flow | Kotlin

     

    kotlinlang.org

     

    sequence & suspend function

    ๋‹จ์ˆœํ•œ ๋ฆฌ์ŠคํŠธ ํ‘œํ˜„์€ List๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

      fun simple(): List<Int> = listOf(1, 2, 3)
     
    fun main() {
        simple().forEach { value -> println(value) } 
    }

     

    ๋งŒ์•ฝ cpu๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์ฐจ๋‹จ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ์—๋Š” sequence๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

    ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ ์—ฐ์‚ฐ์€ 100ms๋งŒํผ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.

     fun simple(): Sequence<Int> =
                    sequence { // sequence builder
                        for (i in 1..3) {
                            Thread.sleep(100) // pretend we are computing it
                            yield(i) // yield next value
                        }
                    }
    
                simple().forEach { value -> println(value) }

     

    ์ด๋ ‡๊ฒŒ sequence๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•œ๋‹ค๋ฉด ์ด๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•œ๋‹ค. ์šฐ๋ฆฌ๋Š” suspend๋ฅผ ํ†ตํ•ด ๊ฐ ์—ฐ์‚ฐ์—์„œ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•˜์ง€ ์•Š๊ณ  ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถœ๋ ฅํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. 

    suspend fun simple(): List<Int> {
        delay(1000) // pretend we are doing something asynchronous here
        return listOf(1, 2, 3)
    }
    
    fun main() = runBlocking<Unit> {
        simple().forEach { value -> println(value) } 
    }

     

    ์—ฌ๊ธฐ์„œ ๋ฐ˜ํ™˜๊ฐ’์„ List<Int>๋ผ๊ณ  ์ž‘์„ฑํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ํ•œ๋ฒˆ์— ๋ชจ๋“  ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›๋Š”๋‹ค. ๋น„๋™๊ธฐ์ ์œผ๋กœ ๊ณ„์‚ฐ๋˜๋Š” ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด์„œ๋Š” Flow<Int>๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๋™๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” sequence<Int>๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

     

    โ„๏ธFlow๋Š” cold์ด๋‹ค!!!

     

    flow๊ฐ€ cold๋ผ๋Š” ๊ฒŒ ๋ฌด์Šจ ๋ง์ผ๊นŒ? 

    flow๋Š” collect๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

    combine ์—ฐ์‚ฐ์ž

    combine์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ flow๋ฅผ ํ•˜๋‚˜์˜ flow๋กœ ๊ฒฐํ•ฉํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฒฐ๊ณผ ์ƒˆ๋กœ์šด flow๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค!


    ์˜ˆ์‹œ์—์„œ ๋“ฑ์žฅํ•˜๋Š” runBlocking์˜ ์—ญํ• ์€? 

    ์œ„์˜ ์˜ˆ์ œ์—์„œ ๋‚˜์˜จ runblocking์€ ์–ด๋–ค ์—ญํ• ์„ ํ•ด์ค„๊นŒ? 

    ์ฝ”๋ฃจํ‹ด ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋ฉด runblocking์„ ์ž์ฃผ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ ์–ด๋–ค ์ƒํ™ฉ์—์„œ ์–ด๋–ค ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

    ์ง€๊ธˆ ์ •๋ฆฌํ•ด๋ณด์ž!! ๐Ÿ™Œ

    fun main() = runBlocking {
        launch {
            delay(1000)
            println("Coroutine 1 finished")
        }
        launch {
            delay(2000) 
            println("Coroutine 2 finished")
        }
        println("runBlocking finished")
    }

     

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

    runblocking : Runs a new coroutine and blocks the current thread until its completion.

     

    1. runblocing ๋‚ด๋ถ€์—์„œ ์ƒˆ๋กœ์šด ์ฝ”๋ฃจํ‹ด์„ ์ƒ์„ฑํ•œ๋‹ค.

    2. ๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ(์ผ๋ฐ˜์ ์œผ๋กœ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ)๋ฅผ ํ•ด๋‹น ์ฝ”๋ฃจํ‹ด์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•œ๋‹ค.

    3. ์ฝ”๋ฃจํ‹ด์ด ์™„๋ฃŒ๋˜๋ฉด runblocking ํ•จ์ˆ˜๋„ ์ข…๋ฃŒ๋œ๋‹ค.

     

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

     

    ์–ด?! ๊ทผ๋ฐ runcatching์ด๋ผ๋Š” ๊ฒƒ๊ณผ๋Š” ๊ทธ๋Ÿผ ๋ญ๊ฐ€ ๋‹ค๋ฅธ๊ฑฐ์ง€?

    runblocking์— ๋Œ€ํ•ด ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๋ฉด 

    - ์ƒˆ๋กœ์šด ์ฝ”๋ฃจํ‹ด์„ ์‹คํ–‰ํ•˜๊ณ  ํ•ด๋‹น ์ฝ”๋ฃจํ‹ด์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•œ๋‹ค.

    - ์ฝ”๋ฃจํ‹ด ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „ํŒŒํ•œ๋‹ค.

    - ์ฃผ๋กœ ์ดˆ๊ธฐํ™” ์ž‘์—…, ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.

     

    runcatching

    - ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

    - ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๊ฒฐ๊ณผ๋ฅผ Result ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

    - ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์ฝ”๋ฃจํ‹ด ์‹คํ–‰์„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ์ •๋ฆฌํ•˜๋ฉด~~~~

    runblocking์€ ์ฝ”๋ฃจํ‹ด์˜ ๋™๊ธฐ์  ์‹คํ–‰์„ ๋ณด์žฅํ•˜๊ณ  ๋”ฐ๋ผ์„œ ์ฝ”๋ฃจํ‹ด์˜ ์‹คํ–‰ ์ˆœ์„œ์™€ ํƒ€์ด๋ฐ์„ ์ œ์–ดํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ  

    runcatching์€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์ฝ”๋ฃจํ‹ด ์‹คํ–‰์„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค!!

     

    728x90