아키텍처 구조를 익히기 위해 여러 레퍼런스를 보며 di 패키지의 존재 이유가 궁금했다.
이를 알아보기 위해 자료를 찾다가 DI IoC DIP라는 용어가 튀어나와 이를 정리해보려고 한다.
코드의 흐름을 제어하는 주체가 바뀌는 것
Android에서 IoC가 적용된 사례
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
/* .. */
}
override fun onPause() {
super.onPause()
/* .. */
}
}
추상화가 아닌 구체클래스에 의존한 사례
class A {
val b = B()
fun text(str: String) = b.call(str)
}
추상화에 의존할 경우
fun main() {
val main = Main()
main.inject()
main.test()
}
interface Test {
fun test(str: String)
}
class TestImpl: Test {
override fun test(str: String) {
println(str)
}
}
class Main {
private lateinit var test: Test
fun inject() {
test = TestImpl()
}
fun test() {
test.test("Test")
}
}
Dependency (의존성)
햄버거 가게 요리사는 햄버거 레시피에 의존하여 요리한다를 코드로 표현해보자class BurgerChef {
private var hamburgerRecipe: HamburgerRecipe
fun cook() {
hamburgerRecipe = HamburgerRecipe().getBurgerRecipe()
}
}
class HamburgerRecipe {
/* .. */
}
의존관계를 interface로 추상화
interface로 추상화 해야한다.class BurgerChef {
private var burgerRecipe: BurgerRecipe
fun cookHamburger() {
burgerRecipe = HamburgerRecipe().getBurgerRecipe()
}
fun cookCheeseBurger() {
burgerRecipe = CheeseBurgerRecipe().getBurgerRecipe()
}
}
interface BurgerRecipe {
getBurgerRecipe()
}
class HamBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): HamburgerRecipe {
return HamburgerRecipe()
}
}
class CheeseBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): CheeseBurgerRecipe {
return CheeseBurgerRecipe()
}
}
Dependency Injection (주입)
의존관계를 외부에서 결정하는 것이기에 클래스 변수를 결정하는 방법들이 곧 DI를 구현하는 방법이 된다. 런타임 시점의 의존관계를 외부에서 주입하여 DI구현을 완성한다.
class BurgerChef(burgerRecipe: BurgerRecipe) {
private var burgerRecipe: BurgerRecipe
this.burgerRecipe = burgerRecipe
fun cook() {
burgerRecipe = burgerRecipe.getBurgerRecipe()
}
}
interface BurgerRecipe {
getBurgerRecipe()
}
class HamBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): HamburgerRecipe {
return HamburgerRecipe()
}
}
class CheeseBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): CheeseBurgerRecipe {
return CheeseBurgerRecipe()
}
}
class Restaurant {
private var burgerChef = BurgerChef(HamburgerRecipe())
fun order() {
burgerChef.cook()
}
}
class BurgerChef() {
private var burgerRecipe: BurgerRecipe
fun setBurgerRecipe(burgerRecipe: BurgerRecipe) {
this.burgerRecipe = burgerRecipe
}
fun cook() {
burgerRecipe = burgerRecipe.getBurgerRecipe()
}
}
interface BurgerRecipe {
getBurgerRecipe()
}
class HamBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): HamburgerRecipe {
return HamburgerRecipe()
}
}
class CheeseBurgerRecipe: BurgerRecipe {
override fun getBurgerRecipe(): CheeseBurgerRecipe {
return CheeseBurgerRecipe()
}
}
class Restaurant {
private var burgerChef = BurgerChef()
fun order() {
burgerChef.setBurgerRecipe(HamburgerRecipe())
burgerChef.cook()
}
}
안드로이드에서 사용되는 DI는 koin, dagger, hilt를 이용하여 구현된다. 이는 이후 알아보도록 할 계획이다.