DI๋ ์ํํธ์จ์ด๊ณตํ์ ๋์์ธ ํจํด ์ค ํ๋๋ค. ์ฉ์ด ๊ทธ ์์ฒด๋ก '์์กด์ฑ์ ์ฃผ์ 'ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
public class User{
val Database mDatabase;
init {
this.mDataBase = Database()
}
}
์ ์ฝ๋๋ฅผ ๋ณด์. User ํด๋์ค์ ์์ฑ์ ๋ด๋ถ์์ Database ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋ค. ๊ทธ๋ ๋ค๋๊ฑด User ํด๋์ค๋ Database ํด๋์ค๊ฐ ์๊ฑฐ๋ ํด๋์ค ๋ด๋ถ์ ์ค๋ฅ๊ฐ ์๋ค๋ฉด ์์ฑ๋ ์ ์๋ ๊ฒ์ธ๋ฐ, ์ด๋ ๊ฒ ๋๋ฉด User ํด๋์ค๊ฐ Database ํด๋์ค์ ์์กด์ ์ด๋ผ๊ณ ํ ์ ์๊ณ , Database ํด๋์ค๋ User ํด๋์ค์ ์ข ์์ฑ์ ์ ๊ณตํ๋ค๋ผ๊ณ ํ ์ ์๋ค.
์ ์ฝ๋์์ User ํด๋์ค๋ Database ํด๋์ค์ ์์กดํ๊ณ ์๋ค๊ณ ํ๊ณ , User ํด๋์ค๋ ์์ฑ์ ๋ด๋ถ์์ Database ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํจ์ผ๋ก์ Database ํด๋์ค์ ๋ํ ์ข ์์ฑ์ ์ป๋๋ค.
์ฌ์ค ์์ ์์์ฒ๋ผ ์์ฑ์๋ฅผ ์ ์ธํ๋ ๊ฒ์ ์๋ก ์์กด๋๊ฐ ๋์ ์ข์ง ์๊ธฐ ๋๋ฌธ์, ์ฐ๋ฆฌ๋ ํด๋์ค๋ฅผ ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก ๋ง๋ค์ด์ค์ผํ๋ค. ๋ ๋ฆฝ์ ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ฉด ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ณ , ๋จ์ ํ ์คํธ๋ฅผ ์ํด์๋ ํ์์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ฐ ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ์๋ฅผ ์ ์ธํ๋ ๊ฒ์ ์ด๋จ๊น? User ํด๋์ค์ ์์ฑ์ ๋ด๋ถ์์ ์ง์ Database๋ฅผ ๊ฐ์ฒดํํ๋ ๊ฒ ๋์ ์, User ์์ฑ์์ argument๋ก ๋ฏธ๋ฆฌ ์์ฑ๋์ด ์๋ Database ์ธ์คํด์ค๋ฅผ ๋๊ธฐ๋ ๊ฒ์ด๋ค.
public class User(val database : Database){
val Database mDatabase;
init {
this.mDataBase = database
}
}
์ด๋ ๊ฒ ํด๋์ค ์ธ๋ถ์์ ์์กด์ฑ(์ ๊ฐ์ง ๊ฐ์ฒด)์ ์ฃผ์
ํ๋ ๊ฒ์ ์์กด์ฑ ์ฃผ์
, ์ฆ Dependency Injection ์ด๋ผ๊ณ ๋ถ๋ฅผ ์ ์๋ค.
DI ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด ๊ฐ๋ฐ์ ํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ๊ณผ ๋จ์ ์ ์ป์ ์ ์๋ค.
์ฅ์
1. ์ ๋ ํ
์คํธ๊ฐ ๊ฐ๋ฅํ๋ค.
2. ์์กด์ฑ ์ด๊ธฐํ๊ฐ ๋ฏธ๋ฆฌ ์ํ๋๋ฏ๋ก ๋ณด์ผ๋ฌ ํ๋ ์ดํธ ์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค.
3. ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถฐ ์ข ๋ ๋
๋ฆฝ์ ์ธ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํ๋ค.
๋จ์
1. ๋ฌ๋์ปค๋ธ๊ฐ ๋๊ณ , ๊ณผ๋ํ๊ฒ ์ฌ์ฉ๋๋ฉด ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
2. ์ปดํ์ผ ์๊ฐ ์๋ฌ๋ก ์ธํด ๋ฐํ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
3. reflection ๋๋ ๋์ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ๊ตฌํ๋๊ธฐ ๋๋ฌธ์ ์์ ํ ๋ฆฌํฉํ ๋ง๊ณผ ๊ฐ์ IDE ์๋ํ ์ฌ์ฉ์ ๋ฐฉํดํ ์ ์๋ค.
์ฌํผ ์ฅ์ ๋ ์๊ณ , ๋จ์ ๋ ์๋ DI์ง๋ง, ๊ฒฐ๋ก ์ ์ผ๋ก ๋งํ์๋ฉด ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ ์ ์๊ณ , ๊ทธ์ ๋ฐ๋ผ ์ ์ง๋ณด์๊ฐ ์ฌ์์ง๋ฉฐ, ๋ชจ๋ ์ฌ์ฌ์ฉ ๋ฐ ์ ๋ ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋ค๋ ๊ฒ ์ฐ๋ฆฌ๊ฐ DI๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ด์ ๋ค.
DI ํ๋ ์์ํฌ์๋ ๋ํ์ ์ผ๋ก Dagger, Dagger Hilt, Koin์ด ์๋๋ฐ, ๋๋ ์์ 2๊ฐ์ ํ๋ ์์ํฌ๋ณด๋ค ๋ฌ๋์ปค๋ธ๊ฐ ๋ฎ๊ณ ์ข ๋ ๊ฐ๋ฒผ์ด Koin์ ์ฐ๋จนํด๋ณด๊ธฐ๋ก ํ๋ค.
Koin์ด๋ ์์ ์ฝํ๋ฆฐ์ผ๋ก ์์ฑ๋ DI ํ๋ ์์ํฌ๋ก, ๋ด๋ถ ๋์์ Service Locator์ ํํ๋ฅผ ๋๋ค. Koin์ ์์ ๋งํ๋ค์ํผ ๋ฌ๋์ปค๋ธ๊ฐ ๋ฎ๊ณ , ์ฝํ๋ฆฐ ๊ฐ๋ฐํ๊ฒฝ์ ๋์ ํ๊ธฐ ์ฌ์ฐ๋ฉฐ, ๋ทฐ๋ชจ๋ธ ์ฃผ์ ์ ์ฝ๊ฒ ํ ์ ์๋ ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํ๋ ์ฅ์ ๋์ ๋ง์ด๋ค ์ฌ์ฉํ๋ค. ๋ค๋ง ์ปดํ์ผ ํ์์ ์ฃผ์ ๋์์ ์ ์ ํ๋ ๋ค๋ฅธ DI ํ๋ ์์ํฌ์ ๋นํด ๋ฐํ์์ Service locating์ ํตํด ๋์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ์ฃผ์ ํ๊ธฐ ๋๋ฌธ์ ๋ฐํ์ ํผํฌ๋จผ์ค๊ฐ ๋ค์ ๋จ์ด์ง ์ ์๊ณ , ์ด๋ก ์ธํด ๋ฐํ์ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ ์ ์๋ค.
Koin์ ์ฃผ์ ํค์๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ฃผ์ ๋ฐ๊ณ ์ ํ๋ ๊ฐ์ฒด์ ์งํฉ์ด๋ค.
์ฑ์ด ์คํ๋๋ ๋์ ๊ณ์ ์ ์ง๋๋ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ฑ๊ธํค scope๋ก ํด๋น ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ ์ ์๋ค. ๋ณดํต repository, retrofit, db๋ฑ์ ์ฌ์ฉํ ๋ ์ฌ์ฉํ๋ค.
์์ฒญํ ๋๋ง๋ค ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. factory๋ก ์ ๊ณต๋๋ ๊ฐ์ฒด๋ ์ปจํ ์ด๋์ ์ ์ฅํ์ง ์์ผ๋ฏ๋ก ๋ค์ ์ฐธ์กฐํ ์ ์๋ค.
viewModel ํค์๋๋ก ๋ชจ๋์ ๋ฑ๋กํ๋ฉด koin์ด ํด๋น ๋ทฐ๋ชจ๋ธ์ ViewModelFactory์ ๋ฑ๋กํ ๋ค ํ์ฌ ์ปดํฌ๋ํธ์ ๋ฐ์ธ๋ฉํ๊ณ , ์ฃผ์ ๋ฐ์ ๋๋ ViewModelFactory์์ ํด๋น ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฌ์จ๋ค.
ํด๋น ์ฝ๋ ๋ฐํ์์ ๋ฐ๋ก ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ๋ค.
get๊ณผ ๊ฐ์ด ์๋ง์ ์์กด์ฑ์ ์ฃผ์
ํ๋, val ๋ณ์์๋ง ์ฌ์ฉํ ์ ์๋ค.
lazy ๋ฐฉ์์ ์ฃผ์
์ผ๋ก, ํด๋น ๊ฐ์ฒด๊ฐ ์ฌ์ฉ๋๋ ์์ ์ ์์กด์ฑ์ ์ฃผ์
ํ๋ค.
koin์ ๋ชจ๋์ ์์ฑํ๊ณ , Application ๋จ์ ํด๋์ค์์ startKoin()์ผ๋ก koin์ ์คํํ์ฌ ํ์ํ ์ปดํฌ๋ํธ์ ์์กด์ฑ์ ์ฃผ์
ํด ์ฌ์ฉํ ์ ์๋ค.
1. Gradle ์ค์
//Koin
def koin_version= "3.1.2"
implementation "io.insert-koin:koin-android:$koin_version"
implementation "io.insert-koin:koin-android-compat:$koin_version"
implementation "io.insert-koin:koin-androidx-workmanager:$koin_version"
implementation "io.insert-koin:koin-androidx-compose:$koin_version"
2. ๋ชจ๋ ์์ฑ
val ViewModelModule = module {
viewModel {MainViewModel(androidApplication())}
}
3. Application ๋จ์ ํด๋์ค์์ ๋ชจ๋ ๋ฑ๋ก ํ manifest์ ์ ์ธ
class App: Application() {
override fun onCreate() {
super.onCreate()
startKoin{
androidContext(this@App)
modules(ViewModelModule)
}
}
}
<application
...
android:name=".App"
</application>
onCreate() LifeCycle์์ startKoin์ ํธ์ถํ๊ณ ์์์ ์ ์ธํ ๋ชจ๋ ๋ณ์๋ฅผ ๋๊ฒจ์ค๋ค.
androidContext(...) : ํด๋น ์๋๋ก์ด๋ context ์ฌ์ฉ
modules(...) : ์ฌ์ฉํ ๋ชจ๋ ๋ฑ๋ก
4. Activity ๋๋ Fragment ๋ด์์ ์์กด์ฑ ์ฃผ์ ๋ฐ๊ธฐ
private val dViewModel: diaryViewModel by inject()
์กํฐ๋นํฐ๋ ํ๋๊ทธ๋จผํธ๊ฐ ์๋ ์ผ๋ฐ ํด๋์ค์์๋ ์์กด์ฑ ์ฃผ์ ์ด ํ์ํ ๋๊ฐ ์๋ค. ํ์ง๋ง ์ผ๋ฐ ํด๋์ค์์๋ get()์ด๋ by inject()๋ฅผ ์ฌ์ฉํด ์์กด์ฑ ์ฃผ์ ์ ํ ์ ์๋ค. ์๋๋ก์ด๋์์ Koin์ ์ฌ์ฉํ ์ ์ปจํ ์ด๋๋ ์๋๋ก์ด๋ ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ์ ๋ง์ถ์ด ์์ฑ๊ณผ ํ๊ดด๊ฐ ๋๋๋ก ๋ง๋ค์ด์ ธ์ผ ํ๋ค. ์กํฐ๋นํฐ๋ ํ๋๊ทธ๋จผํธ ๋ด๋ถ์์ ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๊ฒฝ์ฐ ํด๋นํ๋ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ฐ๋ฅด๊ฒ ์ง๋ง, ์ผ๋ฐ ํด๋์ค์ ๊ฒฝ์ฐ ์๋ช ์ฃผ๊ธฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฌํผ ์ด๋ ๊ฒ ์ผ๋ฐ ํด๋์ค์์ Koin์ ์ฌ์ฉํ๊ธฐ ์ํด KoinComponent๋ผ๋ ๊ฒ์ ์ ๊ณตํ๊ณ ์๋ค. KoinComponent๋ฅผ ์ฌ์ฉํ๋ฉด by inject(), get() ๋ฑ์ ์ฌ์ฉํด ์์กด์ฑ์ ์ฃผ์ ํ ์ ์๋ค.
class MyComponent : KoinComponent {
// lazy inject Koin instance
val myService : MyService by inject()
// eager inject Koin instance
val myService : MyService = get()
}
ํ์ง๋ง ๋ค์์ StackOverFlow, ๊ธฐ์ฌ๋ฅผ ํ์ธํด๋ณด๋ฉด, ์์ฑ์ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์ ๋ฐ์ ์ ์๋ ์ํฉ์ ์ ์ธํ๋ฉด ์ด ๋ฐฉ๋ฒ์ ๊ถ์ฅ๋์ง ์๋๋ค. ๋ฐ๋ผ์ KoinComponent๋ณด๋จ, ์กํฐ๋นํฐ๋ ํ๋๊ทธ๋จผํธ์์ Koin์ ์ฌ์ฉํด์ผ ํ๋ ํด๋์ค๋ฅผ ์์ฑํ ๋ ์์ฑ์๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํ๋ ๊ฒ์ด ์ข๋ค.
class MainActivity : AppCompatActivity() {
private val dataStoreModule : DataStoreModule by inject()
override fun onCreate(savedInstance: Bundle){
super.onCreate(savedInstanceState)
...
Aclass(dataStpreModule)
}
}
class Aclass(private val dataStoreModule: DataStoreModule) {
...
}
https://www.simplifiedcoding.net/android-dependency-injection/#What-is-Dependency
https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f
https://stackoverflow.com/questions/14301389/why-does-one-use-dependency-injection
https://jaejong.tistory.com/153