[Android A..Z] DI Dependency Injection 한 방에 끝내기

2022. 10. 20. 17:52개발/[Kotlin] 안드로이드 개발

반응형

Denpendency Injection(DI)는 개발을 하면 한 번쯤은 들어보고 

무엇인지 찾아보게 되는 개념입니다.

안드로이드를 개발하면서 공부한 DI 개념을 정리하도록 하겠습니다.

1. Dependency Injection(DI)

1-1 Dependency

Dependency는 의존성이라는 뜻입니다.

개발에서의 의존성은 하나의 클래스가 다른 하나의 클래스에 의존하는 것을 의미합니다.

A 클래스가 B 객체를 만드려면 어떻게 할까요?

class A {
 val B = B()
}

이런식으로 만드는 방법이 있습니다.

이렇게 되면 B는 A의 의존의 대상이 됩니다.

B()라는 클래스가 다음과 같이 바뀐다면 어떻게 될까요?

class B(context: Context) {
}

A클래스에서는 B클래스를 객체화 하기 위해서 context라는 객체를 가져와야 합니다.

아니면 B클래스에서 부생성자를 생성해야 합니다.

이렇게 하나의 클래스가 변할 때 다른 클래스에서도 수정작업을 해주거나 별도로 작업이 필요하다는 걸 '의존한다'라고 합니다.

그러면 어떻게 해야할까요? 

현실에 비교해 보면, 자동차 회사는 타이어 부품회사에 의존하고 있고,

타이어 부품회사는 의존의 대상이 됩니다.

각각 Car클래스와 Tire클래스를 생각해 볼 수 있고 Dependency의 개념을 생각할 수 있습니다.

1-2 Injection

Injection은 주입이라는 뜻입니다.

위에서 얘기했던 Car클래스와 Tire클래스의 Dependency를 코드를 통해 보도록 하겠습니다.

class Car(tireAmount: Int) {
    var tire: Tire
    init {
        tire = Tire(tireAmount)
    }
}

Car클래스에서는 Tire클래스의 객체를 생성한 다음 CAr클래스의 객체를 만듭니다.

아래와 같이 Car클래스에서 매번 Tire 객체를 만들어줘야합니다.

이것은 자동차회사에서 Tire를 매번 만들어주는거랑 똑같이 비유할 수 있습니다.

하지만 실제로 자동차회사에서 Tire를 만들지 않고 타이어 회사(한국타이어)에서 주문해서 받아와 조립합니다.

프로그래밍도 그렇게 하자는 것입니다.

외부에서 만들어온 타이어를 그대로 가져와서 조립만 할 수 있게끔요.

 

프로그래밍적으로 접근하자면

Car 클래스에서 Tire 객체를 만드는 것이 아닌,

외부에서 Tire객체를 만들어서 Car클래스를 생성하는 것입니다.

이렇게 외부에서 의존관계가 있는 대상을 가져오는 것을

Dependency Injection 의존성 주입이라고 합니다.

 

이렇게 하면, Car클래스에서는 특별히 다른 타이어에 따라서 코드를 수정할 필요없이,

그냥 inject받아서 사용만 하면 됩니다.

이렇게 되면 단위테스트가 쉬워지고(의존성이 분리되어 있기 때문) 클래스를 수정하는데 있어서 더욱 효과적입니다.

 

1-3 Dependency Injection의 간단한 구현

그러면 자동차와 타이어를 프로그래밍적으로 봐보겠습니다.

아래와 같이 Car클래스가 아닌 외부에서 Tire객체를 만들어서

Car클래스에 만들어진 타이어 객체를 전달해줄 수 있습니다.

fun main() {
    val tire = Tire(80)
    val car = Car(tire)
    car.printTireAmount()
}
class Tire(val tireAmount: Int) {

}

class Car(val tire: Tire) {
   fun printTireAmount() {
       print(tire.tireAmount)
   }
}

코드를 보면 그렇게 어렵지는 않습니다.

하지만 Android에서는 많은 DI Library가 존재합니다. ex) koin, dagger, hilt

이 부분도 자동차에 비교해보면,

자동차를 만들기 위해서는 많은 부품들이 들어가게 되는데

이를 클래스로 만들면 Car클래스에 엄청나게 많은 부품을 수용하는 생성자나 setter메소드가 필요하게 됩니다.

그럼 그에 따라서 생성자나 setter메소드를 모두 관리해주어야하는 필요성이 필요합니다.

 

이러한 부분에서 효율성을 위해

올바른 순서로 생성시키고 객체를 받아들일 수 있도록 관리하는 Hilt와 같은 라이브러리가 필요한 것입니다.

 

반응형