๋ชฉ์ฐจ
์ฝํฌํด์ ์ผ์์ ์ผ๋ก ์คํ์ ์ค๋จํ๊ณ ๋ค์ ์์ํ ์ ์๋ ๊ณ์ฐ์ ์ธ์คํด์ค์ด๋ค.
๊ฐ๋ ์ ์ผ๋ก๋ ์ค๋ ๋์ ์ ์ฌํ์ง๋ง ํน์ ์ค๋ ๋์ ๊ฒฐํฉ๋์ด ์์ง ์๋ค. ๋ค์๋งํด, ์ฝ๋ฃจํด์ ํ ์ค๋ ๋์์ ์คํ์ ์ผ์ ์ค๋จํ๊ณ , ๋ค๋ฅธ ์ค๋ ๋์์ ๋ค์ ์์ํ ์ ์๋ค.
์ค๋ ๋๋ ๋์์ ์ฌ๋ฌ ์์ ์ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ํ๋์ ์ค๋ ๋์์ ๋ฌด์ธ๊ฐ๋ฅผ ๊ธฐ๋ค๋ฆด ๋ ๋ค๋ฅธ ์์ ์ ์ํํ ์ ์๋ค. ํ์ง๋ง ์ค๋ ๋๋ ๋น์ฉ์ด ํฐ ์์ ์ด๊ธฐ ๋๋ฌธ์ ๋ง์ ์ค๋ ๋ ์ฌ์ฉ ์ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์!
์ฝ๋ฃจ์น์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์.
์ฝ๋ฃจํด์ ๋ธ๋ก๋ผ๋ ์ฝ๋ ์กฐ๊ฐ์ ๊ฐ์ง๊ณ ์๊ณ , ์ด ๋ธ๋ก์ ์คํ ์ค์ ์ผ์ ์ค๋จ๋ ์ ์๊ณ , ์ดํ ๋ค์ ์์๋ ์ ์๋ค.
์ด๋ฅผ ์ด์ฉํ์ฌ ์ฝ๋ฃจํด์ ๋ธ๋ก์ ์คํํ๋ฉด์ ํ์ํ ๋๋ง๋ค ๋ค๋ฅธ ์์ ์ผ๋ก ์ ํํ ์ ์๋ค.
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello") // main coroutine continues while a previous one is delayed
}
๊ฒฐ๊ณผ
Hello
World!
์ฝ๋๋ฅผ ์ชผ๊ฐ์ ์ดํดํด๋ณด์!
launch
launch๋ coroutine builder์ด๋ค. ๋จ์ ์ฝ๋์ ํจ๊ป ๋์์ ์๋ก์ด ์ฝ๋ฃจํด์ ์์ํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ ์ฝ๋์ ์คํ ๊ฒฐ๊ณผ๋ก Hello๋ถํฐ ์ถ๋ ฅ๋์๋ค.
delay
delay๋ ํน์ํ ์ผ์ ์ค๋จ ํจ์์ด๋ค. ์ด ํจ์๋ ์ฝ๋ฃจํด์ ํน์ ์๊ฐ๋์ ์ผ์ ์ค๋จ์ํจ๋ค. ์ผ์์ค๋จ์ ์๋ฏธ๋ ํด๋น ์ฝ๋ฃจํด์ด ์ง์ ๋ ์๊ฐ๋์ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ๋ค๋ ์๋ฏธ์ด๋ค. ๊ทธ๋ฌ๋ ์ด๋์ ์ผ์ ์ค๋จ์ ๊ธฐ๋ณธ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ์๋๋ค. ๋์ ๋ค๋ฅธ ์ฝ๋ฃจํด๋ค์ด ์คํ๋๋๋ก ํ์ฉํ๊ณ ๊ธฐ๋ณธ ์ค๋ ๋๋ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ์ํํ ์ ์๋ค.
์๋๋ก์ด๋ ์ฑ์์ ๋คํธ์ํฌ ํธ์ถ์ด๋ ํ์ผ๋ก๋ฉ๊ณผ ๊ฐ์ I/O์์ ์ ์ํํ๋ ๋์ ์ฑ์ด ์๋ต์ด ๋จ์ด์ง๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด delay๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์ด ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ์๊ฐ๋์ ์ผ์ ์ค๋จ๋์ด ๋๊ธฐํ๋ฉด์๋ ๋ค๋ฅธ ์ฝ๋ฃจํด๋ค์ด ์คํ๋ ์ ์๋ค.
runBlocking
runBlocking์ ๋ํ ์ผ๋ฐ์ ์ธ fun main ํจ์์ธ ์ฝ๋ฃจํด์ด ์๋ ์ธ๊ณ ์ runBlocking { } ๋ด๋ถ์ ์๋ ์ฝ๋ฃจํด ์ฝ๋๋ค์ ์ฐ๊ฒฐํ๋ ๋ธ๋ฆฟ์ง๊ฐ์ ์ฝ๋ฃจํด ๋น๋์ด๋ค.
์ฝํ๋ฆฐ์์ ์ฝ๋ฃจํด์ ํญ์ ํน์ ํ corouting scope ๋ด์์ ์คํ๋์ด์ผํ๋ค. runBlocking์ ์ฝ๋ฃจํด ์ค์ฝํ๋ฅผ ์ ๊ณตํ๋ฉด์๋, ์ผ๋ฐ์ ์ธ ํจ์์ธ main๊ณผ ๊ฐ์ ์ฝ๋ฃจํด์ด ์๋ ํ๊ฒฝ์์๋ ์ฝ๋ฃจํด์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ค.
๋ง์ฝ runBlocking์ ์์ด๋ฒ๋ฆฐ๋ค๋ฉด IDE์์๋ ์ค๋ฅ ๋ฉ์์ง๊ฐ ํ์๋๋ค.
์ด์ ๋ launch์ ๊ฒฝ์ฐ CoroutingScope์์ ์ ๊ณต๋๋ ํ์ฅํจ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ launch๋ runBlocking์ด๋ ๋ค๋ฅธ ์ฝ๋ฃจํด ๋น๋์์ด๋ ์ฌ์ฉํ ์ ์๋ค!
์ ๋ฆฌํ์๋ฉด runBlocking์ ์ฝ๋ฃจํด์ด ์ด๋ค ์ค์ฝํ์์ ์คํ๋์ด์ผํ๋์ง ์ ์ํ๊ณ ๋น์ฝ๋ฃจํดํ๊ฒฝ๊ณผ ์ฝ๋ฃจํดํ๊ฒฝ์ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํ๋ค.
runBlocking์ ํด๋น ํจ์๋ฅผ ์คํํ๋ ์ค๋ ๋๊ฐ ํธ์ถ๋๋ ๊ธฐ๊ฐ๋์ ๋ธ๋ก๋๋ฉฐ, runBlocking {...} ๋ธ๋ก ๋ด์ ๋ชจ๋ ์ฝ๋ฃจํด์ด ์คํ์ ์๋ฃํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ํ๋ค.
runBlocking์ ์ฑ์ ์ต์๋จ ์์ค์์ ์ฌ์ฉ๋๋ค. ์ฃผ๋ก main์์ ์ฌ์ฉ๋๋ค.
๊ทธ๋ฌ๋ ์ค์ ์ฝ๋์์๋ runBlocking์ ์ฌ์ฉํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ด์ง ์๋ค. ์ฃผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์์์ด๋ ํ ์คํธ ์ฝ๋์์ ์ฌ์ฉํ๋ค. ๋ณธ๊ฒฉ์ ์ธ ๋น๋๊ธฐ์ฝ๋ ์์ฑ์๋ ๋ค๋ฅธ ์ฝ๋ฃจํด ๋น๋๋ค์ด ๋ ์ ์ ํ๋ค.
Structured concurrency
์ฝ๋ฃจํด์ ๊ตฌ์กฐ์ ๋์์ฑ์ด๋ผ๋ ์๋ฆฌ๋ฅผ ๋ฐ๋ฅด๋๋ฐ,
- ํน์ coroutingscope
์ด ์๋ฆฌ๋ ์๋ก์ด ์ฝ๋ฃจํด์ ํด๋น ๋ฒ์์์ ์์๋ ์ฝ๋ฃจํด์ ์๋ช ์ ์ ํํ๋ CoroutingScope์์์๋ง ์์๋ ์ ์๋ค๋ ์๋ฆฌ์ด๋ค.
- ์๋ช ์ ํ
runBlocking์ ํน์ ํ ์ฝ๋ฃจํด ๋ฒ์๋ฅผ ์ค์ ํ๋ค. ์ด๋ runBlocking {...} ๋ธ๋ก ๋ด์์ ์์๋ ์ฝ๋ฃจํด์ด runBlocking ๋ฒ์์ ๋ฌถ์ฌ ์์ด์ ์ด ๋ฒ์๋ฅผ ๋ฒ์ด๋ ์ ์๋ค๋ ์๋ฏธ์ด๋ค.
- ์๋ฃ ๋๊ธฐ
runBlocking ๋ฒ์ ๋ด์์ ์ฝ๋ฃจํด์ด ์์๋์์ผ๋ฏ๋ก ์ฝ๋ฃจํด์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค. ์์ ์ฝ๋์์ Hello ๋ค์์ 1์ด์ ์ง์ฐ ์๊ฐ ํ์ World!๊ฐ ์ถ๋ ฅ๋๊ณ ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ๋๋ค.
- ๋์ถ ๋ฐฉ์ง
๊ตฌ์กฐ์ ๋์์ฑ์ ์ฝ๋ฃจํด ๋์ถ์ ๋ฐฉ์งํ๋ค. ํน์ ๋ฒ์ ๋ด์์ ์ฝ๋ฃจํด์ ์์ํ๋ฉด ํด๋น ๋ฒ์๋ ์์ ์ฝ๋ฃจํด์ด ๋ชจ๋ ์๋ฃ๋ ๋๊น์ง ์๋ฃ๋์ง ์๋๋ค. ์ด๋ ์ฝ๋ฃจํด์ด ์์ค๋๊ฑฐ๋ ๋ฌดํ์ ์คํ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ค.
- ์๋ฌ์ฒ๋ฆฌ
ํน์ ๋ฒ์ ๋ด์์ ์์๋ ์ฝ๋ฃจํด ๋ด์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ด ์ค๋ฅ๊ฐ ์ ์ ํ๊ฒ ๋ณด๊ณ ๋๋ค.
๋ํ ๊ตฌ์กฐ์ ์ฑ๊ฒฉ์ ์ด๋ฌํ ์ค๋ฅ๋ฅผ ๋์น์ง ์๊ณ ์ฒด๊ณ์ ์ผ๋ก ์ฒ๋ฆฌํ๋๋ก ๋ณด์ฅํ ์ ์๋ค.
Extract function refactoring
์ฒ์ ์ฝ๋
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello") // main coroutine continues while a previous one is delayed
}
๋ฆฌํฉํ ๋งํ ์ฝ๋
fun main() = runBlocking { // this: CoroutineScope
launch { doWorld() }
println("Hello")
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
๊ฒฐ๊ณผ
Hello
World!
suspend modifier์ ๊ฐ์ง ์๋ก์ด ํจ์๋ฅผ ์ป๊ฒ ๋๋ค. ์ด ํจ์๊ฐ ์ฐ๋ฆฌ์ ์ฒซ๋ฒ์งธ suspending function!
suspending function์ ์ผ๋ฐ์ ์ธ ํจ์์ ๊ฐ์ด ์ฝ๋ฃจํด ๋ด์์ ์ฌ์ฉ๋ ์ ์๋ค.
๊ทธ๋ฌ๋ suspending function์ ์ถ๊ฐ์ ์ธ ํน์ง์ ์ฝ๋ฃจํด์ ์คํ์ ์ผ์์ค๋จ ์ํค๋ delay์ ๊ฐ์ suspending function์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด๋ค!
scope builder
๋ค์ํ ๋น๋์ ์ํด ์ ๊ณต๋๋ ์ฝ๋ฃจํด scope ์ด์ธ์๋, coroutineScope builder๋ฅผ ์ฌ์ฉํ์ฌ ๋๋ง์ ์์ฒด scope๋ฅผ ์ ์ธํ ์ ์๋ค. ์ด๊ฒ์ ์ฝ๋ฃจํด ์ค์ฝํ๋ฅผ ์์ฑํ๊ณ ๋ชจ๋ ์์์ด ์๋ฃ๋ ๋๊น์ง ์๋ฃ๋์ง ์๋๋ค.
runBlocking๊ณผ coroutingScope Builder๋ค์ ๋๋ค ๊ทธ๋ค์ body์ ๋ชจ๋ ์์์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ธฐ ๋๋ฌธ์ ๋น์ทํด๋ณด์ผ ์ ์๋ค! ๊ทธ๋ฌ๋ ์ฃผ์ ์ฐจ์ด๊ฐ ์กด์ฌํ๋ค.
runBlocking์ ํ์ฌ์ ์ค๋ ๋๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ธฐ ์ํด ๋ง๋๋ค. ๋ฐ๋ฉด coroutingScope๋ ๊ทธ์ ์ผ์์ค๋จ๋์ด์ ๊ธฐ๋ณธ ์ค๋ ๋(underlying thread)๋ฅผ ๋ค๋ฅธ ์ฉ๋๋ก ํด์ ํ๋ค(release ํ๋ค)
์ด๋ฌํ ์ฐจ์ด๋๋ฌธ์, runBlocking์ ์ผ๋ฐ์ ์ธ ํจ์์ด๊ณ coroutingScope๋ ์ผ์์ค๋จ ํจ์(suspending function)์ด๋ค.
์ฐ๋ฆฌ๋ ์ด๋ ํ suspending function์์๋ coroutineScope๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
์๋ฅผ ๋ค์ด ์ ์ฝ๋์ ๊ฐ์ด Hello์ World๋ฅผ ๋์์ ์ถ๋ ฅํ๋ ๋ถ๋ถ์ suspend fun doWorld( ) ํจ์๋ก ์ฎ๊ธธ ์ ์๋ค.
Scope builder and concurrency
coroutineScope builder๋ (์ฌ๋ฌ ๋์ ์์ ์ ์ํํ๊ธฐ ์ํด) ์ด๋ค ์ผ์์ค๋จ ํจ์ ๋ด์์๋ ์ฌ์ฉํ ์ ์๋ค.
// Sequentially executes doWorld followed by "Done"
fun main() = runBlocking {
doWorld()
println("Done")
}
// Concurrently executes both sections
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
launch {
delay(2000L)
println("World 2")
}
launch {
delay(1000L)
println("World 1")
}
println("Hello")
}
๊ฒฐ๊ณผ
Hello
World 1
World 2
Done
์ฌ๊ธฐ์ launch {...} ๋ด๋ถ์ ๋ ์ฝ๋ ์กฐ๊ฐ๋ธ๋ก์ ๋์์ ์คํ๋๋ค. ๋จผ์ World1์ด ์ถ๋ ฅ๋๊ณ , ์์์ผ๋ก๋ถํฐ 2์ด ํ์ World2๊ฐ ์ถ๋ ฅ๋๋ค.
doWorld ๋ด๋ถ์ coroutingScope๋ ์ค์ง ๋ ๋ค ์๋ฃ๋ ์ดํ์๋ง ์๋ฃ๋๋ค. ๋ฐ๋ผ์ doWorldํจ์๋ Done ๋ฌธ์์ด์ด ์๋ฃ๋ ์ดํ์ ๋ฐํ๋๊ณ ์ถ๋ ฅ๋๋๋ก ํ๋ค.
An explicit job
launch๋ ์์๋ coroutine์ ์ฒ๋ฆฌํ๊ณ ๋ช ์์ ์ผ๋ก coroutine๋ค์ ์๋ฃ๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ ์ฌ์ฉ๋๋ jop ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ corouting builder์ด๋ค .
fun main() = runBlocking {
// Using launch to start a coroutine and get a reference to its Job
val job = launch {
// Simulating some asynchronous task with delay
delay(1000L)
println("World!")
}
// Additional code in the main coroutine while the child coroutine is running
println("Hello")
// Explicitly waiting for the completion of the child coroutine using job.join()
job.join()
// Code after the child coroutine is completed
println("Done")
}
* launch: ์๋ก์ด ์ฝ๋ฃจํด์ ์์ํ๊ณ ๊ทธ๋ค์ job ์ฐธ์กฐ๋ฅผ ์ป๊ธฐ ์ํด launch๋ฅผ ์ฌ์ฉํ๋ค.
* job :lauch๋ก ์์๋ ์ฝ๋ฃจํด์ val job = launch { ...}์ ํตํด Job ๊ฐ์ฒด์ธ job์ ์ป๋๋ค.
* job.join : job์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ผ๊ณ ํ์ฌ์ ์ฝ๋ฃจํด์๊ฒ ๋ช ๋ นํ๋ ํจ์์ด๋ค. ์ด๋ฅผ ํตํด ๋ถ๋ชจ ์ฝ๋ฃจํด์ธ main ์ฝ๋ฃจํด์ ์์ ์ฝ๋ฃจํด์ด ์๋ฃ๋ ๋๊น์ง ์ฐจ๋จ๋๊ณ ๊ทธ ํ์ Done ๋ฌธ์์ด์ด ๋ฐํ๋๋ค.
๊ฒฐ๊ณผ
Hello
World!
Done
Coroutines are light-weight
์ฝ๋ฃจํด๋ค์ JVM ์ค๋ ๋๋ณด๋ค ๋ ์ ์ ์์์ ์ฌ์ฉํ๋ค.
'๐ค2024 ์๋๋ก์ด๋ > ๊ธฐ์์ฌ ํ๋ก์ ํธ ๊ธฐ๋ก' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Compose์์ ๊ตฌ์ฑ๋ณ๊ฒฝ ์ ์ ์ฅ๋์ง ์๋ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ (2) | 2024.01.21 |
---|---|
android Flow ์์๋ณด๊ธฐ (2) | 2024.01.21 |
compose์ preferences datastore ์ด์ฉํ๊ธฐ (1) | 2024.01.18 |
๐ Android FCM ์ ์ฉ๊ธฐ 2ํ : FCM + Retrofit (0) | 2024.01.07 |
๐Android FCM ์ ์ฉ๊ธฐ 1ํ : Notification ํํค์ณ๋ณด๊ธฐ (1) | 2024.01.06 |