Dependency Injection(DI), 우리말로 하면 "종속 항목 삽입" 또는 "의존성 주입" 정도로 번역할 수 있다. DI는 프로그래밍에서 널리 사용되는 기법인데, 이를 이해하기 위해서는 먼저 "Dependency"와 "Injection"이 각각 무엇을 뜻하는지 이해할 필요가 있다.
우리말로는 의존 또는 의존성이라고 할 수 있다. DI에서 Dependency는 하나의 클래스가 다른 하나의 클래스에 의존하는 것을 의미한다.
예를 들어 Car
클래스가 존재한다고 하자. 하나의 자동차를 만들기 위해서는 여러가지 부품이 필요하고 여기에는 Engine
도 포함될 것이다.
따라서 Car
클래스는 Engine
클래스를 참조해야한다. Engine
처럼 필요한 클래스를 Dependency, 종속 항목 이라고 한다.
Injection은 우리말로 주입을 뜻한다.
위의 Car
, Engine
예시를 다시 살펴보자. Car
클래스 인스턴스를 생성하기 위해서 필요한 Engine
객체를 얻는 방법은 세가지가 있다.
1. 클래스에서 직접 필요한 종속 항목을 구성한다.
2. 다른 곳에서 객체를 가져온다. (Context
getter 및 getSystemService()
와 같은 일부 Android API가 이러한 방식으로 작동한다.)
3. 객체를 매개변수로 받는다. 아래 예시에서는 Car
생성자가 Engine
을 매개변수로 받는다.
위의 방식 중 세 번째 방법이 바로 Injection 이다.
class Car(private val engine: Engine) {
fun start() {
engine.start()
}
}
fun main(args: Array) {
val engine: Engine()
val car = Car(engine)
car.start()
}
위의 예시 코드처럼 Car
클래스에서Engine
클래스처럼 필요로하는 종속 항목을 외부에서 가져오는 것을 Dependency Injection이라고 한다.
이와 같은 DI 기반 접근 방법은 여러 장점을 가진다.
Car
의 재사용 가능. Engine
의 다양한 구현을 Car
에 전달할 수 있다. 예를 들어 Engine
이 ElectricEngine
이라는 새로운 Engine
서브클래스를 정의할 수 있는데, 만약 Car
가 클래스 내부에서 자체적으로 Engine
객체를 구성하는 형태라면 이러한 변화에 대응이 어렵다. 하지만 DI를 사용하면 업데이트된 ElectricEngine
인스턴스르 똑같이 Car
에 전달하기만 하면된다.Car
의 테스트 편의성. Car
클래스의 종속 항목인 Engine
클래스가 서로 분리되어 있기 때문에 각각의 코드들에 대해서만 테스트하고 수정하는 것이 가능하다.Android에서 DI를 실행하는 방법은 크게 2가지가 있다.
1. 생성자 삽입 위의 Car
, Engine
예시처럼 생성자에 매개변수로 종속 항목을 받을 수 있다.
2. 필드 삽입(또는 setter 삽입) Android에서는 Activity나 Fragment처럼 특정 클래스는 시스템에서 인스턴스화하므로 생성자 삽입이 불가능하다. 이때 필드 삽입을 사용해서 종속 항목을 클래스 생성 이후 인스턴스화 시킬 수 있다.
class Car{
lateinit var engine: Engine
fun start() {
engine.start()
}
}
fun main(args: Array){
val car = Car()
car.engine = Engine()
car.start()
}
위의 예시를 보면 알겠지만 DI라는 개념이 그렇게 어려운 개념이 아니다. 그리고 개발자가 직접 수동으로 구현하는 것 자체도 그렇게 어렵지 않다. 이를 종속 항목 수동 삽입 이라고 한다.
하지만 위의 예시에서는 Car
클래스의 종속 항목으로 Engine
하나만 요구했지만 실제 자동차는 훨씬 더 많은 부품을 필요로 한다. 엔진 뿐만 아니라 타이어, 휠, 핸들 등... 이렇게 하나의 클래스에 종속 항목이 많아질 경우 수동으로 구현하게 되면 여러 문제점이 발생한다.
프로젝트의 규모가 크고 코드가 많아질수록 DI의 중요성도 커진다. 이를 자동화시켜주기 위한 대표적인 라이브러리가 바로 Dagger다.
Hilt는 Dagger를 기반으로하는 Android에서 종속 항목을 삽입하기 위한 Jetpack 권장 라이브러리이다.
다음 포스트에서는 기존 아키텍처에서 DI를 수동으로 어떻게 구성하는지 알아보자.
레퍼런스)
1. Android의 종속 항목 삽입
2. Dependency Injection(DI)에 대해서 알아보자