์ ๋ฒ์ MVVM๊ณผ ๊ฐ์ด ๋ง์ ์ค๋ฌด ํ๋ก์ ํธ์์ ์ฌ์ฉ๋๋ Dependency Injection์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค. Andorid์์๋ ์ข์ App Architecture๋ฅผ ๊ตฌํํ๊ธฐ ์ํ์ฌ ๊ถ์ฅํ๊ณ ์๋ ์์น์ด๊ธฐ๋ ํฉ๋๋ค. ๋ค๋ค DI๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. ์ข์ App Architecture๋ฅผ ์ํด์ AACํจํด์ ์ ์ฉํ๋ ๊ฒ์ฒ๋ผ DI๋ ๊ฐ์ ๋ชฉ์ ์ ์ํด์ ์ ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ ๊ฒ์ ๋๋ค.
- ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ
- ๋ฆฌํฉํ ๋ง์ ์ฉ์ด์ฑ
- ํ ์คํธ ํธ์์ฑ
Android์์๋ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ์ ์ํ๋ฉด์ DI์ ๋ํ์ฌ ์๊ฐํ๊ณ ์์ต๋๋ค.
class Car { private val engine = Engine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() } |
class Car(private val engine: Engine) { fun start() { engine.start() } } fun main(args: Array) { val engine = Engine() val car = Car(engine) car.start() } |
์ผ์ชฝ ์ฝ๋์ ์ค๋ฅธ์ชฝ ์ฝ๋์ ์ฐจ์ด์ . ๊ทธ๊ฒ์ ๋ช ํํ๊ฒ ์๋ ๊ฒ์ด DI์ ๋ํด์ ๋ ์ ์ดํดํ ์ ์์ต๋๋ค.
๊ทธ๋ฅ ๋ฐ๋ก๋ฐ๋ก ์ฝ๋๋ง ๋ฐ๋ผ๋ณธ๋ค๋ฉด,
”๋ญ๊ฐ ๋ค๋ฅธ๊ฑฐ์ผ? ๊ฒฐ๊ตญ Engineํด๋์ค ์ Carํด๋์ค๋ฅผ mainํจ์์์ ์ฌ์ฉํ๋ ์ฝ๋ ์๋์ผ?”
์ด๋ ๊ฒ ์๊ฐํ์ค ์๋ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทผ๋ณธ์ ์ผ๋ก ์คํํ๋ ๊ฒ์ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ๊ฐ์ ๊ฒฐ๊ณผ ํ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ์ง๋ง, DI ์์กด์ฑ ์ฃผ์ ์ด๋ผ๋ ๋จ์ด์ ๋ํด์ ๋ค์ ํ๋ฒ ์๊ฐํด๋ด ์๋ค.
์ ๊ฐ ์ฝ๋์์ ๋ฐ์ค ๊ทธ์ ๋ถ๋ถ์ ๋ค์ ๋ณด์๋ฉด, Car Class๋ด๋ถ์์ Engine Class๋ฅผ ์ ์ํ๋๋, ํน์ mainํจ์ ๋ด์์ Engine Class์ Car Class๋ฅผ ์ ์ํด์ Car Class์ ๋งค๊ฐ๋ณ์๋ก Engine Class๋ฅผ ๋๊ฒจ์ฃผ๋๋์ ์ฐจ์ด์ ์ ๋ณด์ค ์ ์์ต๋๋ค.
์ด๋ ๋งค๊ฐ๋ณ์๋ก Car Class์ Engine ๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ฃผ๋ ๊ฒ์ด DI ์ข ์์ฑ ์ฝ์ ์ ๋๋ค. Car Class๋ด๋ถ์์ Engine ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ด ์๋๋ผ Engine ๊ฐ์ฒด ์์ฒด๋ฅผ ์์ฑ์์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ต๋๋ค. ์ด๋ ๊ฒ ๋๋ฉด Car๋ Engine์ ์ข ์๋ ์ํ๊ฐ ๋ฉ๋๋ค. ์ด ์ํ์์๋ Engine Class์ ๋ณ๊ฒฝ ์ฌํญ์ด ์๊ธฐ๊ฑฐ๋ Sub Class๋ก ๋ณ๊ฒฝํ์ฌ ์ ์ฉํ ๋์ Car Class์ ์ํฅ์ด ์์ด ์ฝ๋๋ฅผ ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ฐ์ฒด๋ง ๋ณ๊ฒฝํด์ Car Class์ ์ ๋ฌํด ์ฃผ๋ฉด ๋๋๊น์.
์ค์ Android ํ๋ก์ ํธ์์๋ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์์กด์ฑ์ ์ฌ์ฉํ์ง๋ ์๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ด๋ จ ๋ด์ฉ๋ค์ ๊ตฌํํฉ๋๋ค. ์์์ ์ฒ๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ์ง ์๊ณ ๊ตฌํํ ์ข ์์ฑ ์ฃผ์ ์ฝ๋๋ฅผ ์๋ ์์กด์ฑ ์ฃผ์ ์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ์๋๋ก์ด๋์์ ์๊ฐํ๊ณ ์์ต๋๋ค.
ํ์ง๋ง ์ค์ ํ๋ก์ ํธ์์๋ ๋ง์ด ๋ค์ด๋ณด์ จ์ Dagger, KoinDI ๊ทธ๋ฆฌ๊ณ ์์ฆ Android์์ ๋ง์ด ๋ฐ๊ณ ์๋ Hilt ํ๋ ์์ํฌ ๋ฑ์ ์ ํํ์ฌ DI์ ๊ด๋ จํ ๊ตฌํ์ ์งํํ๊ฒ ๋ฉ๋๋ค. ์ ์ ๊ฐ์ธ์ ์ธ ๊ฒฝํ์ผ๋ก๋ Koin DI๋ฅผ ํตํด ์ฃผ๋ก ๊ตฌํ์ ํ์์๊ณ , ํ๋ก์ ํธ์ ์ฑํฅ์ ๋ฐ๋ผ์ ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํ์ฌ ์์กด์ฑ ์ฃผ์ ์ ๊ตฌํํ๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค. “๋ญ๊ฐ ๋ ์ข๊ณ ๋์๋ค”์ ๊ฒฐ์ ์ฌํญ์ด ์๋๋ผ ๊ฐ ์ํฉ์ ๋ง๋ ๊ฐ์ฅ ์ข์ ๋ชจ๋ธ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ๋ต์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์๋์ ๋๋ต์ ์ธ ํฐ ์ฐจ์ด์ ๋ค์ ์์ฑํ์ฌ ๋์์ต๋๋ค.
Dagger | Koin DI | Hilt |
|
|
|
์ ๋ ์ ์๊ฒ ๊ฐ์ฅ ์ต์ํ Koin DI ํ๋ ์์ํฌ๋ฅผ ์ด์ฉํ์ฌ ์ ๋ฒ์ ์์ฑํ๋ mvvm์ฝ๋์ ์ด์ด์ ๊ด๋ จ ์ฝ๋๋ฅผ ์ถ๊ฐํด ๋ณด๋ ค๊ณ ํฉ๋๋ค.
์์ ์น ์ฌ์ดํธ์์ ๊ฐ๋จํ Koin ์ ์ฉ ๋ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
์ผ๋จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๊ณผ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
์ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฒ์ ์ ๋ฐ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ์ฌ koin_version์ ํตํด ๋ฐ๋ก ์ง์ ํด ์ฃผ์์ต๋๋ค.
ํ์ฌ ์ต์ ๋ฒ์ ์ 3.2.0 version์ ๋๋ค.
buildscript {
repositories {
mavenCentral()
}
}
ext {
koin_version = '3.2.0'
}
dependencies {
...
// Koin for Android
implementation "io.insert-koin:koin-android:$koin_version"
}
Application() ํด๋์ค๋ฅผ ์์๋ฐ์์ ๊ทธ ๋ด๋ถ์ Koin DI๋ฅผ ์คํ์ํค๋ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
startKoin ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ Koin์ ์คํ์ํค๊ณ modules()๋ฅผ ํตํ์ฌ ์ปจํ
์ด๋์ ๋ก๋ํ module ๋ชฉ๋ก์ ์ง์ ํ์ฌ ์ฃผ๋ ์ฝ๋์
๋๋ค.
package com.dev_seonhan.mvvm
import android.app.Application
import com.dev_seonhan.mvvm.di.appModule
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin
class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(this@BaseApplication)
modules(appModule)
}
}
}
์๋์ ๊ฐ์ด module์ ๋ํ ๋ชฉ๋ก์ ์์ฑํด์ฃผ๋ฉด ๋๋๋ฐ ์ด๋ ๋ ๊ฐ์ง์ ์์ฑ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ ์ธํ ์ ์์ต๋๋ค.
Classical DSL Way | Constructor DSL Way |
val appModule = module { // single instance of HelloRepository single<HelloRepository> { HelloRepositoryImpl() } // Simple Presenter Factory factory { MySimplePresenter(get()) } } |
val appModule = module { // single instance of HelloRepository singleOf(::HelloRepositoryImpl) { bind<HelloRepository>() } // Simple Presenter Factory factoryOf(::MyPresenter) } |
์ฝ๊ฐ์ ํํ์ ์ฐจ์ด๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ ๋ TextUtil Interface๋ฅผ ์์ฑํ๊ณ TextUtilImpl class๋ฅผ ์์ฑํ์ฌ ์์ ๊ฐ์ด ์ข ์์ฑ ์ฃผ์ ์ ํด์ฃผ์์ต๋๋ค.
package com.dev_seonhan.mvvm.di
import com.dev_seonhan.mvvm.utils.TextUtil
import com.dev_seonhan.mvvm.utils.TextUtilImpl
import org.koin.dsl.module
val appModule = module {
single<TextUtil> { TextUtilImpl() }
}
single, factory, scoped์ ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์ฒด ์ธ์คํด์ค์ ์ ๊ณต ๋ฐฉ์์ ์ง์ ํ ์ ์์ต๋๋ค.
์๋์ ํด๋น ์ปดํฌ๋ํธ๋ค์ ๊ฐ๋จํ ๋ด์ฉ๋ค์ ์ ๋ฆฌํ์ฌ ๋์์ต๋๋ค
single | factory | scoped |
|
|
|
ํด๋น ์ปดํฌ๋ํธ๋ค์ ๊ฐ๋จํ ๋ด์ฉ๋ค์ ์ ๋ฆฌํ์ฌ ๋์์ต๋๋ค.
์์์ ๊ฐ๋จํ๊ฒ ์ปจํ ์ด๋์ ๋ด๊ธธ ๋ชจ๋์ single ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ lazy ํ๊ฒ ์์ฑํ๋๋ก ํ์๋๋ฐ, ์ด๊ฒ์ ํ์ํ ๊ณณ์์ by inject(), get()ํ์ฌ ๊ฐ์ฒด๋ฅผ ๋ฐ์์ค๋ฉด ๋ฉ๋๋ค.
val mtestTextUtilFirst: TextUtil by inject()
์์ ๊ฐ์ด by inject()๋ฅผ ์ด์ฉํ์ฌ ๋ณ์์ ์ ์ธ ์์ lazyํ๊ฒ ํธ์ถ ์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ด ์๊ณ , ์๋์ get()์ ์ด์ฉํ์ฌ ๋ฐ๋ก ์ฃผ์ ๋ฐ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ด์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mTestTextUtilSecond: TextUtil = get()
}
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋จํ๊ฒ ์์กด์ฑ ์ฃผ์
์ด ๋ฌด์์ธ์ง, ๊ทธ๋ฆฌ๊ณ Koin DI ํ๋ ์์ํฌ๋ฅผ ์ด์ฉํ DI์ ์ฉ ๋ฐฉ๋ฒ์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์์ฝํด๋ณด์์ต๋๋ค.
์ด ๊ธ์ด ๋ชจ๋ ๋ด์ฉ์ ๋ด๊ณ ์์ง๋ ์๊ธฐ ๋๋ฌธ์ ์ค์ ์ ํ๋ก์ ํธ์์๋ ๋ ์์ธํ ๋ด์ฉ๋ค์ด ํ์ํ๊ฒ ์ง๋ง, ๊ทธ๊ฒ๋ค ๋ํ ์ฐจ์ฐจ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.

'๐ป ๊ฐ๋ฐ์ ์ด์ผ๊ธฐ > ์๋๋ก์ด๋ ์ฝ์ง๊ธฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Kotlin์ Coroutine, ์ฝ๋ฃจํด #1 (0) | 2023.01.31 |
---|---|
Navigation, ์์ฃผ ๊ฐ๋จํ๊ฒ Fragment๊ฐ์ ์ ํ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ. (0) | 2022.10.20 |
[Android Build Issue] : [hilt] (2) | 2022.10.19 |
์ฝ๊ณ ๋น ๋ฅด๊ฒ ์ด๋ฏธ์ง ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ, Glide Library (0) | 2022.10.18 |
MVVM์ ๋ํ์ฌ, ๊ทธ๋ฆฌ๊ณ ๊ฐ๋จํ ์ํ์ฝ๋๋ฅผ ๋ง๋ค์ด๋ณด๊ธฐ (0) | 2022.08.31 |