[Android] Dependency Injection(DI)란?

문승연·2023년 9월 20일
0

Android 기초

목록 보기
4/8

Dependency Injection(DI), 우리말로 하면 "종속 항목 삽입" 또는 "의존성 주입" 정도로 번역할 수 있다. DI는 프로그래밍에서 널리 사용되는 기법인데, 이를 이해하기 위해서는 먼저 "Dependency"와 "Injection"이 각각 무엇을 뜻하는지 이해할 필요가 있다.

Dependency

우리말로는 의존 또는 의존성이라고 할 수 있다. DI에서 Dependency는 하나의 클래스가 다른 하나의 클래스에 의존하는 것을 의미한다.

예를 들어 Car 클래스가 존재한다고 하자. 하나의 자동차를 만들기 위해서는 여러가지 부품이 필요하고 여기에는 Engine 도 포함될 것이다.
따라서 Car 클래스는 Engine 클래스를 참조해야한다. Engine 처럼 필요한 클래스를 Dependency, 종속 항목 이라고 한다.

Injection

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

이와 같은 DI 기반 접근 방법은 여러 장점을 가진다.

  1. Car의 재사용 가능. Engine 의 다양한 구현을 Car에 전달할 수 있다. 예를 들어 EngineElectricEngine 이라는 새로운 Engine 서브클래스를 정의할 수 있는데, 만약 Car 가 클래스 내부에서 자체적으로 Engine 객체를 구성하는 형태라면 이러한 변화에 대응이 어렵다. 하지만 DI를 사용하면 업데이트된 ElectricEngine 인스턴스르 똑같이 Car 에 전달하기만 하면된다.
  2. 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 하나만 요구했지만 실제 자동차는 훨씬 더 많은 부품을 필요로 한다. 엔진 뿐만 아니라 타이어, 휠, 핸들 등... 이렇게 하나의 클래스에 종속 항목이 많아질 경우 수동으로 구현하게 되면 여러 문제점이 발생한다.

  1. 대규모 앱에서 모든 종속 항목을 가져와 올바르게 연결하려면 대량의 상용구 코드가 필요해진다. 다중 레이어 아키텍처에서는 상위 레이어로 갈수록 아래 레이어에 있는 모든 종속 항목을 제공해야한다.
  2. 종속 항목을 전달하기 전에 구성할 수 없을 때 (ex. lateinit 등을 사용할 때)는 메모리에서 종속 항목의 전체 기간을 관리하는 맞춤 컨테이너(or 종속 항목 그래프)를 작성하고 유지해야한다.

프로젝트의 규모가 크고 코드가 많아질수록 DI의 중요성도 커진다. 이를 자동화시켜주기 위한 대표적인 라이브러리가 바로 Dagger다.

HiltDagger를 기반으로하는 Android에서 종속 항목을 삽입하기 위한 Jetpack 권장 라이브러리이다.

다음 포스트에서는 기존 아키텍처에서 DI를 수동으로 어떻게 구성하는지 알아보자.

레퍼런스)
1. Android의 종속 항목 삽입
2. Dependency Injection(DI)에 대해서 알아보자

profile
"비몽(Bemong)"이라는 앱을 개발 및 운영 중인 안드로이드 개발자입니다.

0개의 댓글