๋ณธ ๊ฒ์๊ธ์ Coroutine ๊ฐ๋ ์ Android ๋ด์์ ์ฌ์ฉ๋๋ ๊ฒ์ ์ ์ ๋ก ์์ฑ๋์๋ค.
#1 ๋ค์ค ์ค๋ ๋ ๊ตฌํ
#1-1 ์ฝ๋ฃจํด
Android์ Kotlin ์ฝ๋ฃจํด | Android Developers
Android์ Kotlin ์ฝ๋ฃจํด ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. ์ฝ๋ฃจํด์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ์ฝ๋๋ฅผ ๊ฐ์ํํ๊ธฐ ์ํด Android์์ ์ฌ์ฉํ ์ ์๋ ๋
developer.android.com
์ปดํจํฐ ๊ณผํ์์์ ๋ฉํฐํ์คํน(Multitasking)์๋ ํฌ๊ฒ 2๊ฐ์ง ์ข
๋ฅ์ด ์๋๋ฐ, ์ฒซ ๋ฒ์งธ ์ข
๋ฅ๋ ์ด์์ฒด์ ๊ฐ ์์์ ํ๋ก์ธ์ค๋ค์ ์ ํํ๋ ๋ฐฉ๋ฒ์ด๊ณ , ๋ ๋ฒ์งธ ์ข
๋ฅ๋ ํ๋ก์ธ์ค ์์ฒด์์ ์ค์ค๋ก์ ๋์์ ์ ์ดํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ ์๋ ์ด์์ฒด์ ์ ์ค์ผ์ฅด๋ฌ๊ฐ ์ํํ๋ค. ๊ฐ๋ฐ์๊ฐ ๊ด์ฌํ์ง ์๋๋ค. ๋ฐ๋ฉด, ํ์๋ ํ๋ก์ธ์ค์ ์ฑ๋ฅ ํฅ์์ ์ํด ๊ฐ๋ฐ์๊ฐ ํ์ฐ์ ์ผ๋ก ๊ด์ฌํด์ผ ํ๋ค.
ํ๋ก์ธ์ค๋ฅผ ์ชผ๊ฐ๋ฉด, ํ๋ก์ธ์ค์ ์ต์ ๋จ์์ธ ์ค๋ ๋๊ฐ ๋๋ค. ๋ ๋ฒ์งธ ์ข
๋ฅ๋ ์ด๋ค ์์
์ด ์ฌ๋ฌ ์ค๋ ๋๋ฅผ ์ค๊ฐ๋ฉฐ ์ํ(๋ฉํฐ์ค๋ ๋ฉ)๋ ์ ์๊ฒ ๋ง๋ ๋ค. ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๊ฐ๋ฐ์๋ ๊ทธ ํ๋ฆ์ ๋ช
์์ ์ธ ์ฝ๋๋ก ์ง์ฃผ์ด์ผ ํ๋ค.
๋ ๋ฒ์งธ ์ข
๋ฅ์ ๊ตฌํ์ ์ํ RxJava, AsyncTask, Executors, HandlerThreads, IntentServices ๋ฑ ๋ง์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์์๋ค. ํ์ง๋ง, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๊ฝค ์ค๋๋์๋ค๊ณ ํ๋ค. Kotlin์ Coroutines(์ฝ๋ฃจํด)์ ๋ํ ๋ ๋ฒ์งธ ์ข
๋ฅ๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๋ฐ, ์์ ์ ์ฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋นํด ์ฝ๊ณ ํจ์จ์ ์ด๋ค.
#1-2 ๋ค์ค ์ค๋ ๋ ๊ตฌํ์ ํ์์ฑ
๋๋ถ๋ถ์ ์ค๋งํธํฐ์ 1์ด(1000๋ฐ๋ฆฌ์ด)์ ์ ์ด๋ 60๋ฒ ํ๋ฉด์ ๊ฐฑ์ (Refresh)ํ๋ค. ์ฆ (1000 / 60) = 16.666...๋ฐ๋ฆฌ์ด์ ์ ์ด๋ ํ ๋ฒ ์ด์ ํ๋ฉด์ Refreshํ๋ค. ๊ทธ๋ฌ๋, ์๋๋ก์ด๋ ์ด์์ฒด์ ์ Main Thread๋ XML ํ์ผ์ ์ธ์คํด์คํํ๊ฑฐ๋ ์ฌ์ฉ์์์ ์ํธ์์ฉ์ ์ฒ๋ฆฌํ๋ ๋ฑ ์ด๋ฏธ ํ ๊ฒ ๋๋ฌด๋๋ ๋ง๋ค. ์ด๋ฐ ์ํฉ์์ ํ๋ฉด ๊ฐฑ์ ๋ง์ Main Thread์์ ์คํ๋๋ค๋ฉด, ์ค๋งํธํฐ์ ๊ต์ฅํ ๋๋ ค์ง ๊ฒ์ด๋ค. ๋๋ฆฐ ์ค๋งํธํฐ์ ๋๊ฐ ์ด๊น? ๋ค์ค ์ค๋ ๋ฉ ๊ตฌํ(๋ฉํฐ์ค๋ ๋ฉ)์ ์ฌ์ค ์์ ์๋ฌด๋ผ๋ ์ด์ผ๊ธฐ๋ค.
#2 ๋ค์ค ์ค๋ ๋์ ํ์์ฑ ์ฒด๊ฐํ๊ธฐ
์ํ ์ฑ์ ํตํด ๋ค์ค ์ค๋ ๋์ ํ์์ฑ์ ์ฒด๊ฐํด๋ณธ๋ค.
#2-1 ์ธ๊ด

Count++ ๋ฒํผ์ ๋๋ฅด๋ฉด ์ค์์ ์ซ์๊ฐ 1์ฉ ์ปค์ง๋ค. ์๋จ์ Download Data ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ฐ์ดํฐ ๋ค์ด๋ก๋๋ฅผ ํ๋ด๋ธ ์์
์ ์ํํ๋ค.
#2-2 MainActivity.kt
// package com.example.coroutinesbasics
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private var count = 0
private lateinit var tvCount: TextView
private lateinit var btnCount: Button
private lateinit var btnDw: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvCount = findViewById(R.id.tvCount)
btnCount = findViewById(R.id.btnCount)
btnDw = findViewById(R.id.btnDw)
btnCount.setOnClickListener {
tvCount.text = count++.toString()
}
btnDw.setOnClickListener {
downloadData()
}
}
private fun downloadData() {
for (i in 1..100000) {
Log.i("interfacer_han", "Downloading data $i in ${Thread.currentThread().name}")
}
}
}
Downlad Button ํด๋ฆญ ๋ฆฌ์ค๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ด๋ก๋ํ๋ ๋์์ '๊ทธ๋ด ๋ฏ ํ๊ฒ ํ๋ด๋ด์ด' ๊ตฌํํ๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ๋ง ๋ค์ด๋ก๋ ํ๋ ๋์ , 10๋ง๊ฐ์ Log๋ฅผ ๋ฐ์์ํจ๋ค. ์ด๋ ์ชฝ์ด๋ ์ค๋ ์๊ฐ๋์ ์คํ๋๋ ์์
์ด๋ผ๋ ์ ์์ ์ ์ฌํ๋ค.
#2-3 ๋์ ํ์ธ

์๋๋ผ๋ฉด Count++ ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ทธ ์์ ์๋ ์ซ์๊ฐ ์ฆ์ ์ฆ๊ฐํด์ผ ํ๋ค. ํ์ง๋ง, Download Data ๋ฒํผ์ ๋๋ฅธ ์ฆ์ ๋ฐ๋ก Count++ ๋ฒํผ์ ๋๋ฅด๋ฉด, ๋ช ์ด ์๋ค๊ฐ Count๊ฐ ์ฆ๊ฐ๋๋ค. ์ฌ์ง์ด ์ค๊ฐ์ ์๋๋ก์ด๋ ์์คํ
์ด ์ฑ์ ๋ฒ๋ฒ
์์ ๊ฐ์งํ๊ณ , ์ฑ์ ์ข
๋ฃ์ํฌ ์ง ๋๊ธฐํ ์ง๋ฅผ ๊ณ ๋ฅด๋ ๋ฉ์์ง๊น์ง ๋ฌ๋ค.
์ด์ ๋ ์ด๋ ๋ค. Download Data ๋ฒํผ์ ๋๋ฅด๋ฉด ์คํ๋๋ 10๋ง๊ฐ์ Log๋ "main" ์ค๋ ๋์์ ๋ฐ์๋๋ค. ๊ทธ๋์ ๊ฐ์ ๋ฉ์ธ ์ค๋ ๋์ธ Count++ ๋ฒํผ์ ๋์์ด ์ฐ์ ์์์์ ๋ฐ๋ ค๋ ๊ฒ์ด๋ค.
์ด๋ฐ ์ฑ์ PlayStore์ ์ฌ๋ฆฐ๋ค๋ฉด ์ข์ ํ๊ฐ๋ฅผ ๋ฐ์ ์ ์์ ๊ฒ์ด๋ค.
#3 Coroutines ์ฌ์ฉํ๊ธฐ
#2๋ฅผ ์์ ํด Coroutines์ผ๋ก ๋ฉํฐ์ค๋ ๋ฉ์ ๊ตฌํํ๊ณ , ๊ฒฐ๊ณผ์ ์ผ๋ก ์ฑ์ ๋ฒ๋ฒ
์์ ํด์ํด๋ณธ๋ค.
#3-1 build.gradle.kts (Module)์์ Coroutines ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ค์ด๋ก๋
plugins {
...
}
android {
...
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2") // ์ฝ๋ฃจํด
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC2") // ์ฝ๋ฃจํด
...
}
์ฌ๊ธฐ์ ์๋ implementation ๊ตฌ๋ฌธ์ ์ฐธ์กฐํ์ฌ, ์ฝํ๋ฆฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ชจ๋ ์์ค build.gradle.kts์์ ๋ค์ด๋ก๋ํ๋ค. ์ด์ ๋ถํฐ ์ฝ๋ฃจํด API๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋์๋ค.
#3-2 MainActivity.kt
...
class MainActivity : AppCompatActivity() {
...
private lateinit var btnDwCoroutine: Button
override fun onCreate(savedInstanceState: Bundle?) {
...
btnDwCoroutine = findViewById(R.id.btnDwCoroutine)
...
btnDwCoroutine.setOnClickListener {
CoroutineScope(Dispatchers.IO).launch {
downloadData()
}
}
}
...
}
Download Data ๋ฒํผ ์ธ์ Download With Coroutine ๋ฒํผ์ ์ถ๊ฐํ๋ค. CoroutineScope๋ ์ฝ๋ฃจํด์ ์ฝ๋๊ฐ ๋ด๊ธธ ์์ญ(Scope)๋ฅผ ์ ํ๊ธฐ ์ํ ์ธํฐํ์ด์ค๋ค. ์ฆ, ์ฝ๋ฃจํด์ ํฌ์ฅ์ง๋ค. ํด๋น ์ฝ๋๋ ๋งค์ฐ ๊ธฐ์ด์ ์ธ Coroutines ๊ตฌ๋ฌธ์ด๋ค. ๋ ์์ธํ ์ค๋ช
ํน์ ๋ฌธ๋ฒ์ ์ฌ๊ธฐ์ ์ฌ๊ธฐ์ ํ์ธํ๋ค. ๋ณธ ๊ฒ์๊ธ์์ ๋ฌธ๋ฒ๋ณด๋จ ์ฝ๋ฃจํด์ด ์๊ณ ์๊ณ ์ ์ฐจ์ด๋ฅผ ํ์ธํ๋ ๋ฐ ์ง์คํ๋ค.
#3-3 ๋์ ํ์ธ

#2-3์ ๋์ผํ ์ํฉ์์ ์ด๋ฒ์ Download Data ๋ฒํผ ๋์ Download With Coroutine ๋ฒํผ์ ๋๋ฌ๋ณด์๋ค. ๋ฒ๋ฒ
์์ด ์ ํ ์์ด ๋ฐ๋ก ์ซ์๊ฐ ์ฆ๊ฐํ๋ค.
#4 ์์ฝ
์๋๋ก์ด๋์์ ๋ฉํฐ์ค๋ ๋ฉ ํ์ฉ์ ํ์๋ค. ์ฝ๋ฃจํด์ ๋ฉํฐ์ค๋ ๋ฉ์ ์ฝ๊ฒ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
#5 ์์ฑ๋ ์ฑ
android-practice/coroutines/CoroutinesBasics at master ยท Kanmanemone/android-practice
Contribute to Kanmanemone/android-practice development by creating an account on GitHub.
github.com
'๊นจ์ ๊ฐ๋ ๐ > Kotlin' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Kotlin] Coroutines - Suspend vs Block (0) | 2024.02.09 |
---|---|
[Kotlin] Coroutines - ๋๊ธฐ ์ฝ๋, ๋น๋๊ธฐ ์ฝ๋ (0) | 2024.02.08 |
[Kotlin] ๋๋ค(Lambda) ํํ์ (0) | 2024.02.01 |
[Kotlin] ํจ์ ํ์ (Fuction types) ํํ์ (0) | 2024.01.31 |
[Kotlin] ํจ์ํ ์ธํฐํ์ด์ค (Single Abstract Method Interface) (0) | 2024.01.30 |