์๋ ํ์ธ์
์ค๋์ ์ฝํ๋ฆฐ์ Coroutine์ ๋ํ์ฌ
ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค.

Coroutine์ด๋?
ํ๋ก๊ทธ๋๋ฐ์์ ํ๋์ ์์ ๋จ์๋ฅผ Routine์ด๋ผ ํ๋๋ฐ
๊ฐ Routine์ด ํ์ (Co)ํ์ฌ ์์ ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ ํฉ์น๊ฒ ๋์ด Co + Roitine์ด๋ผ ๋ช ๋ช ํ๊ณ ์์ต๋๋ค.
Coroutine์ Thread์์ ์คํ๋๋ ์์ Thread๋ผ ํธ์นญํ ์ ์์ผ๋ Thread์ ๊ฐ์ด ์์ ์ ์ฌ์ฉํ ์คํ์
๋ฐ๋ก ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ์ฒด ๋จ์๋ก ์์ฑ๋ฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด Thread๋์ Coroutine์ ๊ตณ์ด ์ฌ์ฉํ๋ ์ด์ ๋ ๋ฌด์์ผ๊น์?? ๐ค
Thread๋ค์ ์ฌ์ฉํ์ฌ Thread๊ฐ Context Switching์ ์ค๋ฒํค๋๊ฐ ๋ง์ด ๋ฐ์ํ ๋ฟ๋ง ์๋๋ผ,
Thread๊ฐ Task ์คํ๋์ค Block์ด ๋ฐ๋ณต ๋๋ค๋ฉด Thread ์ฑ๋ฅ์ ์ ๋๋ก ํ์ฉํ์ง ๋ชปํ๊ฒ ๋๊ธฐ ๋๋ฌธ์
Coroutine์ ์ฌ์ฉํ์ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋ค๊ณ ํฉ๋๋ค.
โ๏ธContext Switching์ด๋?
ํ์ฌ ์งํํ๊ณ ์๋ Task(Process, Thread)์ ์ํ๋ฅผ ์ ์ฅํ๊ณ
๋ค์ ์งํํ Task์ ์ํ ๊ฐ์ ์ฝ์ด ์ ์ฉํ๋ ๊ณผ์ ์ ๋งํฉ๋๋ค.
์ฐธ์กฐ : https://nesoy.github.io/articles/2018-11/Context-Switching
Context Switching์ด๋?
nesoy.github.io
์ด์ ๋ Coroutine์ ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋ํ์ฌ ์์๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ Coroutine์ Kotlin ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ Gradle ํ์ผ์ dependency๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผ ํฉ๋๋ค.
์ ๊ฐ์ ๊ฒฝ์ฐ๋ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์์ง๋ง ์๋ ๋งํฌ์์ ์ฝ๋ฃจํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฒ์ ์ ๋ค๋ฅธ ๋ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฐพ์ ์ ์์ต๋๋ค.
์ฝ๋ฃจํด ๋ฟ๋ง ์๋๋ผ ์ฌ๋ฌ๊ฐ์ง ํธ๋ฆฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฐพ์๋ณผ ์ ์์ผ๋ ๊ถ๊ตผํ์ ๋ถ๋ค์ ํ๋ฒ์ฉ ํ์ธํด๋ณด์๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค :)
์ฐ์ Coroutine์๋ ํฌ๊ฒ 2๊ฐ์ง์ interface๊ฐ ์กด์ฌํ๋๋ฐ
๋ฐ๋ก CoroutineContext , CoroutineScope์ ๋๋ค.
CoroutineContext๋?
์ฝ๋ฃจํด ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํ ๊ฒ์ธ์ง์ ๋ํ ์์(Element)๋ค์ ์งํฉ์ผ๋ก Dispatcher์ Job์ด ์์๋ค๋ก ์กด์ฌํฉ๋๋ค.
Dispatcher์ Coroutine์ ์ฒ๋ฆฌํ Thread๋ฅผ Setting ํ๊ณ ํ ๋นํ๋ ์ญํ ์
Job์ ์์ฑ๋ Coroutine์ ๊ด๋ฆฌํ๋ ์ญํ ์ ์ํํฉ๋๋ค.
Job๊ฐ์ฒด์ ํจ์๋ค
ํจ์๋ช | ์ค๋ช |
start() | ํ ์ฝ๋ฃจํด์ ์ํ๋ฅผ ์์๋ด์ด ์์ or ์ค๋น/์ข ๋ฃ |
join() | ํ ์ฝ๋ฃจํด์ด ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆผ |
cancel() | ํ ์ฝ๋ฃจํด์ ์ข ๋ฃ |
cancelAndJoin() | ํ ์ฝ๋ฃจํด์ ์ข ๋ฃํ๊ณ ๋๊ธฐ |
cancelChildren() | ํ CoroutineScope๋ด์ ์์ฑ๋ ๋ชจ๋ ์์ ์ฝ๋ฃจํด๋ค์ ์ข ๋ฃ |
Dispatcher์ ์ข ๋ฅ ๋ฐ ์ค๋ช
์ด๋ฆ | ์ค๋ช |
Dispatcher.Main | ์๋๋ก์ด๋์์๋ง ์กด์ฌํ๋ Dispatcher๋ก ์๋๋ก์ด๋ Main Thread(UI Thread)์์๋ง ์ฌ์ฉํ๋ Dispatcher์
๋๋ค. โ๏ธ ๋ฐ๋์ UI์ ์ํธ์์ฉ์ ํ ์์๋ง ์ฌ์ฉํด์ผ ํฉ๋๋ค. |
Dispatcher.IO | ์ /์ถ๋ ฅ ์์ ์ ํนํ๋ Dispatcher |
Dispatcher.Default | CPU ์์ ๋์ด ๋ง์ ์์ ์ ์ฌ์ฉ๋๋ Dispatcher (Sorting , ๋ ๋๋ง ๋ฑ) |
Dispatcher.UnConfined | ํน์ํ ์ํฉ์์ ์ฝ๋ฃจํด์ ์คํํ ๋ ์ฌ์ฉ (์ฌ์ฉ์ด ๊ถ์ฅ๋์ง ์์ ) |
CoroutineScope๋?
Coroutine Block(Area)์ ์์ฑํ๋ ์ญํ ์ ์ํํ๋ฉฐ Coroutine์ด ์คํ๋๋ ๋ฒ์๋ฅผ ๋ํ๋ ๋๋ค.
CoroutineScope์ ํ์ฅ ํจ์์ธ Coroutine Builder๋ฅผ ํตํด ๋ง์ด ์ฌ์ฉํ๋ฉฐ
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ Builder๋ async์ launch์ ๋๋ค.
์๋ ์์ ์ฝ๋์ ํจ๊ป ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.
launch
๊ฒฐ๊ณผ ๋ฐํ์ด ํ์ ์๋ ์์ ์ ํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ฉฐ Job๊ฐ์ฒด๋ฅผ ๋ฆฌํด ๋ฐ์ ํด๋น ์ฝ๋ฃจํด์ ๊ด๋ฆฌ ํ ์ ์์ต๋๋ค.
/**
MutableList์ ์ ์ฅ๋ ๊ฐ๋ค์ ๋ชจ๋ ๋ํ๋ ํ์ฅ ํจ์
**/
class ExtensionFunctions {
companion object{
fun MutableList<Int>.elementSum() : Int {
var sum = 0
forEach{
sum += it
}
return sum
}
}
}
import com.lee.coroutine.functions.ExtensionFunctions.Companion.elementSum
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
suspend fun main() {
buildLaunch()
}
suspend fun buildLaunch() {
println("${Thread.currentThread().name}์์")
with(CoroutineScope(Dispatchers.Default)){
var sum1 = 0
var sum2 = 0
var increment = 1
val jobObj1 = launch{
sum1 = (1..100).toMutableList().elementSum()
delay(1000L)
println("${Thread.currentThread().name}๋ด์ ์ฝ๋ฃจํด ${increment++}์ข
๋ฃ")
}
val jobObj2 = launch {
sum2 = (1..100).toMutableList().elementSum()
delay(1000L)
println("${Thread.currentThread().name}๋ด์ ์ฝ๋ฃจํด ${increment++}์ข
๋ฃ")
}
jobObj1.join()
jobObj2.join()
println("๋ ๋ฆฌ์คํธ์ ์ดํฉ์ ${sum1 + sum2}์
๋๋ค.")
}
}
suspend ํจ์์ ๋ํด์..
suspend ํค์๋๋ ํด๋น ํค์๋๋ฅผ ์ ์ธํจ์ผ๋ก์จ ์ฝ๋ฃจํด ๊ฐ์ฒด์์ ์์ ์ด ๋๋ ๋๊น์ง ์ ์ ํจ์๋ฅผ ๋ฉ์ถ ์ ์์ต๋๋ค.
ํด๋น ํจ์๊ฐ ๋ฉ์ถฐ ์๋ ๋์ ๋ค๋ฅธ ์์ ์ด ์งํ๋๋ฉฐ ๋ฉ์ถฐ์๋ ํจ์์ ์์ ์ด ์ข ๋ฃ๋๋ฉด ๋ค์ ํจ์๋ก ๋์์ ๋ค์ ์ฒ๋ฆฌ๋ฅผ ์งํํฉ๋๋ค.
์ฝ๋ฃจํด์์ ๋ฉ์ถค๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋์๋ ๋ฐ๋์ suspend๋ก ์ ์ธํด์ฃผ์ด์ผ ํ๋ฉฐ
suspend ํจ์๋ suspend๋ก ์ ์ธ๋ ํจ์ ๋ด๋ถ ํน์ ์ฝ๋ฃจํด ๋ธ๋ญ์์๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ ์ฝ๋๋ 1~100์ ๊ฐ์ ๊ฐ์ง๊ณ ์๋ 2๊ฐ์ ๋ฆฌ์คํธ์ ํฉ์ ๋ํ๋๋ก ํ๋ ๊ฐ๋จํ ํ๋ก๊ทธ๋จ์ ๋๋ค.
CoroutineScope๋ฅผ ํตํด ์ฝ๋ฃจํด์ ์ฌ์ฉํ ๋ธ๋ญ์ ์ง์ ํ๊ณ launch๋ฅผ ํตํด ์ฝ๋ฃจํด์ ์์ฑํ๊ณ ์์ผ๋ฉฐ
๊ฐ ์ฝ๋ฃจํด๋ค์ Job๊ฐ์ฒด๋ก ๊ด๋ฆฌ๋์ด join()์ ํตํด ์์ ์ด ๋๋ ๋๊น์ง ๋๊ธฐํฉ๋๋ค.
async
๊ฒฐ๊ณผ ๋ฐํ ๊ฐ์ด ์์ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ฉฐ ๋ฐํ ๊ฐ์ Deferred<T>์ ๋๋ค.
await()๋ฅผ ํตํด Deferred์ ๊ฐ์ธ์ ธ ์๋ ๊ฐ์ ๋ฐํ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import com.lee.coroutine.functions.ExtensionFunctions.Companion.elementSum
import kotlinx.coroutines.*
suspend fun main() {
buildAsync()
}
suspend fun buildAsync() {
println("${Thread.currentThread().name} ์์")
with(CoroutineScope(Dispatchers.Default)){
var increment = 1
var value1 = 0
var value2 = 0
val resultOne : Deferred<Int> = async {
println("${Thread.currentThread().name}๋ด์ ์ฝ๋ฃจํด ${increment++}์ข
๋ฃ")
(1..100).toMutableList().elementSum()
}
val resultTwo : Deferred<Int> = async {
println("${Thread.currentThread().name}๋ด์ ์ฝ๋ฃจํด ${increment++}์ข
๋ฃ")
(1..100).toMutableList().elementSum()
}
value1 = resultOne.await()
value2 = resultTwo.await()
println("๋ ๋ฆฌ์คํธ์ ์ด ํฉ์ ${value1 + value2}์
๋๋ค.")
}
}
์ ์ฝ๋์ ๊ฒฐ๊ณผ ๊ฐ์ launch ์์ ์ ๊ฐ์ผ๋ฉฐ
launch ๋์ async๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ฆฌํด ๋ฐ์ ์ฌ์ฉํ๋ ์ฝ๋์ ๋๋ค.
์ 2๊ฐ์ง ํจ์๋ค ์ธ์๋ withContext(CoroutineScope)์ runBlocking()์ด ์กด์ฌํ๋ฉฐ
withContext๋ async์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ์ ๋ฐํํ์ง๋ง Deferred <T> ํ์ ์ด ์๋ ๋จ์ํ T ํ์ ์ผ๋ก ๋ฐํํฉ๋๋ค.
suspend fun buildWithContext() {
val value = withContext(Dispatchers.Default){
// ๋ง์ง๋ง์ ๋ฐํ๊ฐ์ ์ง์ ํด์ฃผ๋ฉด Deferred๋ก ๋ฌถ์ด์ง ์๊ณ ๋ฐ๋ก ๋ฐํ๋๋ค.
(1..100).toMutableList().elementSum()
}
println("๊ฐ์ $value")
}
runBlocking()์ Thread์์ ํด๋น ํจ์๊ฐ ํธ์ถ ์ ํธ์ถ๋ ๋ถ๋ถ์์ Block ๋์ด runBlocking() ํจ์ ๋ด๋ถ์
์ฝ๋ฃจํด๋ค์ด ๋ชจ๋ ์ข ๋ฃ๋ ๋๊น์ง ํจ์๋ฅผ ์ ์ง์์ผ ๋๊ธฐํ๋ ๊ฐ์ ์ป๊ณ ์ ํ ๋ ์ฃผ๋ก ์ฌ์ฉํฉ๋๋ค.
์ด์์ผ๋ก ์ฝ๋ฃจํด์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋ง์น๊ฒ ์ต๋๋ค.
๋ค์ ํฌ์คํ ์ผ๋ก๋ Coroutine์ Channel๊ณผ Flow์ ๋ํ์ฌ ๊ณต๋ถํ ๋ด์ฉ์ ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค. ๐
๊ทธ๋ผ ๋ค์ ํฌ์คํ ์์ ๋ต๊ฒ ์ต๋๋ค.
์ค๋๋ ์ฆ์ฝํ์ธ์ :)
'Tutorial > tutorial' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin] ์ฝํ๋ฆฐ Coroutine์ ๋ํ์ฌ (3) - Coroutine Flow(ํ๋ก์ฐ) (0) | 2022.10.13 |
---|---|
[Kotlin] ์ฝํ๋ฆฐ Coroutine(์ฝ๋ฃจํด)์ ๋ํ์ฌ (2) - ์ฝ๋ฃจํด Channel(์ฑ๋) (0) | 2022.10.11 |
[Kotlin] ์ฝํ๋ฆฐ Thread(์ค๋ ๋)์ ๊ดํ์ฌ (0) | 2022.10.04 |
[Kotlin] ์ฝํ๋ฆฐ ์ฌ๋ฌ๊ฐ์ง Collection์ ๋ํ์ฌ (0) | 2022.09.29 |
[Kotlin] ์ฝํ๋ฆฐ Property ์์ (0) | 2022.09.27 |