KDY

DI? Dependency Injection란 무엇일까? 본문

개념

DI? Dependency Injection란 무엇일까?

daeyeong 2022. 6. 2. 19:40

개발을 진행하다 보면 DI를 많이 들어봅니다.

 

그렇다면 이 DI? 도대체 무엇일까요? 그래서 오늘은 DI에 대해 알아볼 것입니다.

 

DI란?


Dependency Injection의 줄임말로 Dependency(의존성) Injection(주입)입니다.

의존성 주입은 하나의 객체가 다른 객체의 의존성을 제공하는 기술입니다. 비유하자면 '의존성'은 서비스로 사용할 수 있는 객체이고 '주입'은 의존성(서비스)을 사용하려는 객체로 전달하는 것을 의미합니다. DI는 프로그래밍에 널리 사용되는 기법으로, DI의 원칙을 따르면 훌륭한 앱 아키텍처를 위한 토대를 마련할 수 있습니다.

예를 한 번 들어보겠습니다.

저희 집이 이불가게를 하므로 이불가게로 예를 들어보겠습니다.

 

//이불가게 업무 클래스
class QuiltShopTask{
	fun orderQuilt() //이불 재고를 주문하는 함수
}

//이불가게 사장님 클래스
class Owner{
    val quiltTask = QuiltShopTask()
    fun work(){
    	quiltTask.orderQulit()
    }
}

위처럼 이불가게 업무(QuiltShopTask) 클래스가 있고, 이불가게 사장님(Owner) 클래스가 있습니다.

이때 Owner클래스에 QuiltShopTask의 요소(orderQuilt)가 있습니다. 이때 이관계가 의존관계이고 

정확히는 Owner가 QuiltShopTask에 의존하고 있다고 할 수 있습니다.

 

이처럼 한 요소에(Owner)에 다른 객체의 요소(QuiltShopTask)가 한 번 등장하면, 그 뒤로 그 객체는(QuiltShopTask) 없어지면 안 됩니다. 예를 들어, 의존 대상인 QuiltShopTask 클래스가 사라지면, Owner객체는 바로 컴파일이 불가능해지고 동작할 수 없는 상태가 됩니다. 그래서 이런 관계를 "의존"이라고 부릅니다.

 

만역 이불가게 사장님이 업종을 음식점으로 바꿨다면 코드를 다음같이 바꿔야 합니다.

class restaurantTask{
    fun orderIngredient()
}

class Owner{
	val restaurantTask = restaurantTask()
    fun work(){
       restaurantTask.orderIngredient()
    }
}

지금은 하나의 요소(orderInredient)만을 사용하기 때문에 그렇게 불편 하지는 않습니다. 하지만 요소가 많다면?

일일이 하나씩다 바꿔야 하는 일 이 발생할 수 있습니다. 이는 곧 코드의 재사용성과 유연성을 떨어트리게 되어 코드의 유지보수를 어렵게 하는 원인이 됩니다.

Dependency injection 이란?

interface StoreTask{
    fun order ()
}

class QuiltTask : StoreTask{
    override fun order() { //이불 주문하는 코드}
}

class resturantTask : StoreTask{
    override fun order() { //음식재료 주문하는 코드}
}

class Owner(task : StoreTask){
	private var task = StoreTask()
    init{
    	this.task = task //Owner안의 task변수와 StorTask Type의 task 연결
    }
    
    fun changeStore(newStoreTask : StoreTask) {
        this.task = newStoreTask //현재 task를 새로운 task로 변경 
    }
    
    fun work(){
    	task.order()
    }
 }
 
 fun main(args: Array<String>) {
 	//초기 이불가게를 운영하시는 사장님
    val owner = Owner(QuiltStoreTask())

    // 음식점으로 직종을 변경하신 사장님
    owner.changeStore(resturantTask())
}

위와 같이 의존하는(필요한) 클래스를 직접 생성하는 것이 아니라, 생성자와 메서드를 통해 외부에서 주입해줌으로써 객체 간의 결합도를 줄이고 좀 더 유연한 코드를 작성할 수 있게 되었습니다. 이제 사장님이 이불가게나 음식점으로 업종을 변경해도, StoreTask 인터페이스를 구현한 이불가게 클래스나 음식점 클래스를 만들어 사용하기만 하면 됩니다.

 

Android에서는 Dagger,Hilt,Koin등의 프레임워크를 사용하여 간단하게 만들 수 있습니다.