์ฝ๋ฃจํด์ด๋?
์ฝ๋ฃจํด์ ์ง์ฐ๊ฐ๋ฅํ ์ธ์คํด์ค์ด๊ณ ๋น์ ์ ํ(OS๊ฐ ๋ค๋ฅธ ์ฌ์ฉ์์๊ฒ๋ก ๊ฐ์ ์ ํํ๋) ๋ฉํฐํ์คํน์ ์ํํ๋ ์๋ธ๋ฃจํด(==ํจ์)์ ์ผ๋ฐํํ ๊ฒ์ด๋ค. "์ง์ฐ๋๋ค"๋ ์๋ฏธ๋ ํน์ ์์ ์ ๋ฉ์ถฐ๋๊ณ ์ฐ์ฐํ๋ค์, ํ์์ ๋ฐ๋ผ ์ฌ์ฉํ ์ง ๋ง ์ง ๊ฒฐ์ ํ๋ค๊ณ ์ดํดํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. ์ฝ๋ฃจํด์ ์ฐ๋ ๋์ ๋นํด ์ ์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๋ค๋ ์ฅ์ ์ด ์๋ค.
์๋ธ๋ฃจํด:
์ฌ๋ฌ ๋ช ๋ น์ด๋ฅผ ๋ชจ์ ์ด๋ฆ์ ๋ถ์ฌํด ๋ฐ๋ณตํธ์ถ ๊ฐ๋ฅํ๊ฒ ์ ์ํ ํ๋ก๊ทธ๋จ ๊ตฌ์ฑ ์์
ํธ์ถ ์ ์๋ธ๋ฃจํด ์ง์ ํ๋ฉฐ ํ์ฑ ๋ ์ฝ๋๊ฐ ์คํ์ ํ ๋น๋๋๋ฐ ์ด ์์ ์ ์๋ธ๋ฃจํด ๋ด๋ถ ๋ก์ปฌ ๋ณ์๋ฑ์ด ์ด๊ธฐํ ๋๋ค. ๋ฐํ ํ๋ฉด ํ์ฑ๋ ์ฝ๋๊ฐ ์คํ์์ ์ฌ๋ผ์ง๋ฉฐ ๋ชจ๋ ์ํ๋ฅผ ๋ ๋ฆฐ๋ค.
์ฝ๋ฃจํด์ ์ข ํฉํ๋ฉด ์๋ก ํ๋ ฅํด ์คํ์ ์ฃผ๊ณ ๋ฐ์ผ๋ฉฐ ์๋ํ๋ ์ฌ๋ฌ ์๋ธ๋ฃจํด์ ๋งํ๋ค.
์ด๋ค ํจ์ A๊ฐ ์คํ๋๋ค๊ฐ ์ ๋ค๋ ์ดํฐ์ธ ์ฝ๋ฃจํด B๋ฅผ ํธ์ถํ๋ฉด A๊ฐ ์คํ๋๋ ์ค๋ ๋ ์์์ ์ฝ๋ฃจํด B์ ์คํ์ด ์์๋๋ค. ์ฝ๋ฃจํด B๋ ์คํ์ ์งํํ๋ค๊ฐ ์คํ์ A์ ์๋ณดํ๋ค. A๋ ๋ค์ ์ฝ๋ฃจํด์ ํธ์ถํ๋ ๋ฐ๋ก ๋ค์ ๋ถ๋ถ๋ถํฐ ์คํ์ ๊ณ์ ์งํํ๋ค๊ฐ ๋ ์ฝ๋ฃจํด B๋ฅผ ํธ์ถํ๋ค.
B์ ์ ์ฒด๊ฐ ์ผ๋ฐ์ ์ธ ํจ์๋ผ๋ฉด ๋ก์ปฌ ๋ณ์๋ฅผ ์ด๊ธฐํํ๋ฉด์ ์ฒ์๋ถํฐ ์คํ์ ๋ค์ ์์ํ๊ฒ ์ง๋ง, ์ฝ๋ฃจํด์ด๋ฉด ์ด์ ์ ์คํ์ ์๋ณดํ๋ ์ง์ ๋ถํฐ ์คํ์ ๊ณ์ํ๊ฒ ๋๋ค.(์ง์ฐ)
์ฝํ๋ฆฐ์ ์ฝ๋ฃจํด ์ง์: ์ผ๋ฐ์ ์ธ ์ฝ๋ฃจํด
kotlinx.coroutines๊ฐ ์ ๊ณตํ๋ ์ฝ๋ฃจํด ๋ช๊ฐ์ง๋ฅผ ๋จผ์ ์์๋ณด์.
์ฐ์ kotlinx.coroutines.core ๋ชจ๋์ ์๋ ์ฝ๋ฃจํด ๋น๋๋ค์ด๋ค.
- kotlinx.coroutines.CoroutineScope.launch
: ์ฝ๋ฃจํด์ Job์ผ๋ก ๋ฐํํ๋ฉฐ, ๋ง๋ค์ด์ง ์ฝ๋ฃจํด์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฆ์ ์คํ๋๋ค. Job์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ cancel, join๊ณผ ๊ฐ์ ์กฐ์์ด ๊ฐ๋ฅํ๋ค. launch์ ์์ ๊ฐ์ฒด๋ CoroutineScope๋ค.
runBlocking์ launch์ ์์ ๊ฐ์ฒด๋ก ์ฌ์ฉํ๋ฉด ๋ด๋ถ์ฝ๋ฃจํด์ด ๋ชจ๋ ๋๋ ๋๊น์ง ์ฐ๋ ๋๋ฅผ ์ ์ ํ๋ค.
์๋ก ๋ค๋ฅธ ์ฝ๋ฃจํด์ด ํ ์ค์ฝํ์์ ์์๋ yield๋ฅผ ์ฌ์ฉํ๋ฉด ์ ์ด๊ถ์ ๋๊ธธ ์ ์๋ค. ์ด๋ ์ ์ด๋ฅผ ๋๊ธด ์ฝ๋ฃจํด์ด delay ์ํ๋ผ๋ฉด ๋ค์ ์ ์ด๊ถ์ด ๋์์ค๊ฒ ๋๋ค. - kotlinx.coroutines.CoroutineScope.async
async๋ ์ฌ์ค์ launch์ ๊ฐ์ ์ผ์ ํ๋ค. launch๊ฐ Job์ ๋ฐํํ๋ ๋ฐ๋ฉด async๋ Deffered๋ฅผ ๋ฐํํ๋ค. Deffered์ Job์ ์ฐจ์ด๋, Job์ ์๋ฌด ํ์ ํ๋ผ๋ฏธํฐ๊ฐ ์๋๋ฐ Deffered๋ ํ์ ํ๋ผ๋ฏธํฐ๊ฐ ์๋ ์ ๋ค๋ฆญ ํ์ ์ด๋ผ๋ ์ ๊ณผ Deffered ์์๋ await() ํจ์๊ฐ ์ ์๋ผ ์๋ค๋ ์ ์ด๋ค. Deffered์ ํ์ ํ๋ผ๋ฏธํฐ๋ ๋ฐ๋ก Deffered ์ฝ๋ฃจํด์ด ๊ณ์ฐ์ ํ๊ณ ๋๋ ค์ฃผ๋ ๊ฐ์ ํ์ ์ด๋ค. ๋ชจ๋ async ํจ์๋ค์ด ๋ฉ์ธ ์ค๋ ๋ ์์์ ์คํ๋๋ ๋น๋๊ธฐ ๋น๋๋ผ๊ณ ์ดํด ํ ์ ์๋ค.
์ฝ๋ฃจํด ์ปจํ ์คํธ์ ๋์คํจ์ฒ
CoroutineScope์๋ CoroutineContext ํ๋๊ฐ ์๋๋ฐ ์ค์ ๋ก ์ฝ๋ฃจํด์ด ์คํ์ค์ธ ์ฌ๋ฌ ์์ (Job)๊ณผ ๋์คํจ์ฒ๋ฅผ ์ ์ฅํ๋ ์ผ์ข ์ ๋งต์ด๋ผ๊ณ ํ ์ ์๋ค. ์ฝํ๋ฆฐ ๋ฐํ์์ ์ด๊ฑธ ์ด์ฉํด ๋ค์ ์คํํ ์์ ์ ๋ฐฐ์นํ๋ค.
launch { // context of the parent, main runBlocking coroutine
println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
println("Default : I'm working in thread ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}
์ ๋ฌํ๋ ์ปจํ ์คํธ์ ๋ฐ๋ผ ์๋ก ๋ค๋ฅธ ์ค๋ ๋์์ ์ฝ๋ฃจํด์ ์คํํ๋ค.
์ฝ๋ฃจํด ๋น๋์ ์ผ์ ์ค๋จ ํจ์
- produce: ์ ํด์ง ์ฑ๋๋ก ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆผ์ผ๋ก ๋ณด๋ด๋ ์ฝ๋ฃจํด์ ๋ง๋ ๋ค. ์ด ํจ์๋ ReceiveChannel<>์ ๋ฐํํ๋ฉฐ ๊ทธ ์ฑ๋๋ก๋ถํฐ ๋ฉ์์ง๋ฅผ ์ ๋ฌ๋ฐ์ ์ฌ์ฉํ ์ ์๋ค.
- actor: ์ ํด์ง ์ฑ๋๋ก ๋ฉ์ธ์ง๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํ๋ ์กํฐ๋ฅผ ์ฝ๋ฃจํด์ผ๋ก ๋ง๋ ๋ค. ์ด ํจ์๊ฐ ๋ฐํํ๋ SendChannel<> ์ฑ๋์ send() ๋ฉ์๋๋ฅผ ํตํด ์กํฐ์๊ฒ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์๋ค.
delay์ yield๊ฐ์ ํจ์๋ ์ผ์์ค๋จ suspending ํจ์๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ผ์์ค๋จ ํจ์๋ค์ด๋ค
- withContext - ๋ค๋ฅธ ์ปจํ ์คํธ๋ก ์ฝ๋ฃจํด ์ ํ
- withTimeout - ์ ํด์ง์๊ฐ์์ ์คํ๋์ง์์ผ๋ฉด ์์ธ์ฒ๋ฆฌ
- withTimeoutOrNull - null ๋ฐํ
- awaitAll - ๋ชจ๋ ์์ ์ ์ฑ๊ณต์ด ๋๋๋ฉด ์ด ํจ์๋ ์ฑ๊ณต. ํ๋๋ผ๋ ์์ธ ๋ฐ์์ ์ด ํจ์๋ ์์ธ ์ฒ๋ฆฌ
- joinAll - ๋ชจ๋ ์์ ์ด ๋๋ ๋ ๊น์ง ํ์ฌ ์์ ์ผ์์ ์ง
suspend ํค์๋์ ์ฝํ๋ฆฐ์ ์ผ์ ์ค๋จ ํจ์ ์ปดํ์ผ ๋ฐฉ๋ฒ
์ผ์ ์ค๋จ ํจ์ ์์์ yield()๋ฅผ ํด์ผ ํ๋ ๊ฒฝ์ฐ
- ์ฝ๋ฃจํด์ ์ง์ ํ ๋์ ์ฝ๋ฃจํด์์ ๋๊ฐ ๋ ์ฝ๋ฃจํด์ด ์คํ ์ค์ด๋ ์ํ๋ฅผ ์ ์ฅํ๊ณ ๋ณต๊ตฌํ๋ ๋ฑ์ ์์ ์ ํ ์ ์์ด์ผ ํ๋ค.
- ํ์ฌ ์คํ ์ค์ด๋ ์์น๋ฅผ ์ ์ฅํ๊ณ ๋ค์ ์ฝ๋ฃจํด์ด ์ฌ๊ฐ๋ ๋ ํด๋น ์์น๋ถํฐ ์คํ์ ์ฌ๊ฐํ ์ ์์ด์ผ ํ๋ค.
- ๋ค์์ ์ด๋ค ์ฝ๋ฃจํด์ ์คํํ ์ง ๊ฒฐ์ ํ๋ค.
์ด ์ธ ๊ฐ์ง ๋์ ์ค ๋ง์ง๋ง ๋์์ ์ฝ๋ฃจํด ์ปจํ ์คํธ์ ์๋ ๋์คํจ์ฒ์ ์ํด ์ํ๋๋ค.
- Dispatchers.Default: ๋์คํจ์ฒ์ ๋ฐ๋ก context๊ฐ ์ง์ ๋์ง์์ผ๋ฉด ์ด๊ฒ ์ฌ์ฉ๋๋ค. ๊ณต์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฐ๋ ๋์ ๊ณต์ฉ ํ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ CPU๋ฆฌ์์ค๊ฐ ๋ง์ด ํ์ํ ์์ ์ ์ ํฉํ๋ค.
- Dispatchers.IO: ์์ฒญํ ๋ ์๊ธฐ๋ ์ฐ๋ ๋์ ๊ณต์ ํ์ ์ฌ์ฉํ๊ณ ํ์ผ์ ์ถ๋ ฅ, ์์ผ์ ์ถ๋ ฅ ์ฐจ๋จ๊ณผ ๊ฐ์ ์์ ์ ์ฌ์ฉ๋๋ค. ์ด๊ฑธ Offloading์ด๋ผ๊ณ ํ๋๋ฐ CPU๊ฐ TCP/IP ํ๋ก์ธ์ฑํ๋ ๊ฑธ ๋ง์์ ์ฑ๋ฅ์ ์ฌ๋ฆฌ๋ ์์ ์ด๋ค.
- Dispatchers.Unconfined: ์ฝ๋ฃจํด ๋น๋๊ฐ ๋ฐํ๋๋ ์ฒซ ์ง์ ๊น์ง ์ฝ๋ฃจํด์ ์คํํ๋ค. ์ค๋จ๋ ์ฝ๋ฃจํด์ ํด๋น ์ค๋จ ํจ์์์ ์ฌ์ฉํ๋ ์ฐ๋ ๋์์ ์ฌ์์๋๋ค. ๋ฐ์ ์กฐ๊ธ ๋ ์์ธํ ์ ๋ฆฌํ์๋ค.
์ผ์ ์ค๋จ ํจ์๋ฅผ ์ปดํ์ผํ๋ ์ปดํ์ผ๋ฌ๋ ์์ ๋ ๊ฐ์ง ์์ ์ ํ ์ ์๋ ์ฝ๋๋ฅผ ์์ฑํด ๋ด์ผ ํ๋ค. ์ด๋ ์ฝํ๋ฆฐ์ ์ปจํฐ๋ด์์ด์ ํจ์ฑ ์คํ์ผ Continuation Passing Style(CPS)๊ณผ ์ํ๊ธฐ๊ณ State Machine๋ฅผ ํ์ฉํด ์ฝ๋๋ฅผ ์์ฑํด๋ธ๋ค. CPS ๋ณํ์ ํ๋ก๊ทธ๋จ์ ์คํ ์ค ํน์ ์์ ์ดํ์ ์งํํด์ผ ํ๋ ๋ด์ฉ์ ๋ณ๋์ ํจ์(์ด๋ฐ ํจ์๋ฅผ Continuation ์ด๋ผ ๋ถ๋ฅธ๋ค.)๋ก ๋ฝ๊ณ ๊ทธ ํจ์์๊ฒ ํ์ฌ ์์ ๊น์ง ์คํํ ๊ฒฐ๊ณผ๋ฅผ ๋๊ฒจ์ ์ฒ๋ฆฌํ๊ฒ ๋ง๋๋ ์์ค์ฝ๋ ๋ณํ ๊ธฐ์ ์ด๋ค.(์ผ์ข ์ ์ฝ๋ฐฑ ์คํ์ผ)
public static final Object example(int v, @NotNull Continuation var1)
suspend ํจ์๊ฐ ์ปดํ์ผ๋ ๋ชจ์ต์ด๋ค. Continuation์ผ๋ก ๋ฐํ๊ฐ์ ์ฒ๋ฆฌํ๋ ๊ฑธ ๋ณผ ์ ์๋ค.
"๋๊ธ, ๊ณต๊ฐ ๋ฒํผ ํ ๋ฒ์ฉ ๋๋ฅด๊ณ ๊ฐ์ฃผ์๋ฉด ํฐ ํ์ด ๋ฉ๋๋ค"
'๐๐๏ธ > ์ฝํ๋ฆฐ ์ธ ์ก์ ๐' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Kotlin in action(8) (0) | 2023.10.10 |
---|---|
Kotlin in action(7) (0) | 2023.10.10 |
Kotlin in action(6) (0) | 2023.10.10 |
Kotlin in action(5) (0) | 2023.10.10 |
Kotlin in action(4) (0) | 2023.10.10 |