DI(Dependency Injection)이란?

Kuno17·2023년 5월 1일
0

CS공부

목록 보기
6/17
post-thumbnail

DI란?

의존관계 주입이라고 한다.

의존관계란?

  • A가 B를 의존한다 = 의존대상 B가 변하면, 그것이 A에 영향을 미친다.

햄버거 가게 요리사는 햄버거 레시피에 의존한다. 햄버거 레시피가 변화하게 되었을 때, 변화된 레시피에 따라서 요리사는 햄버거 만드는 방법을 수정해야 한다. 레시피의 변화가 요리사의 행위에 영향을 미쳤기 때문에, “요리사는 레시피에 의존한다”고 말할 수 있다. 코드로 표현해보면 다음과 같다.

class BurgerChef {
	private HamBurgerRecipe hambergerRecipe;
    
    public BurgerChef() {
    	hamBugerRecipe = new HamBurgerRecipe();
	}
}

의존관계를 인터페이스로 추상화한다!

위 BurgerChef 예시를 만들어 보자.
지금의 구현에서는 HamBurgerRecipe만을 의존할 수 있는 구조로 되어있다.
더 다양한 BurgerRecipe를 의존 받을 수 있게 인터페이스로 추상화할 수 있다.

class BurgerChef { 
	private BurgerRecipe burgerRecipe;
    
    public BurgerChef() {
    	burgerRecipe = new HamBurgerRecipe();
        //burgerRecipe = new CheeseBurgerRecipe();
        //burgerRecipe = new ChickenBurgerRecipe();
   }
}
   
interface BurgerRecipe {
   newBurger();
   //이외의 다양한 메서드
}

class HamBurgerRecipe implements BurgerRecipe {
	public Burger newBurger() {
    	reture new HamBurger();
        }
        //...
}

의존관계를 인터페이스로 추상화한다. → 결합도가 낮아진다. → 더 다양한 의존 관계를 맺을 수 있다.


그렇다면 DI는?

의존관계가 무엇인지에 대해, 그리고 다양한 의존관계를 위해 인터페이스로 추상화함을 알아봤다. 그렇다면, Dependency Injection은 무엇인가?

지금까지의 구현에서는 BurgerChef 내부적으로 의존관계인 BurgerRecipe가 어떤 값을 가질지 직접 정하고 있다
만약 어떤 BurgerRecipe를 만들지를 버거 가게 사장님이 정하는 상황을 상상해보자. 즉, BurgerChef가 의존하고 있는 BurgerRecipe를 외부(사장님)에서 결정하고 주입하는 것.

DI의 구현방법 3가지

Burger 레스토랑 주인이 어떤 레시피를 주입하는지 결정하는 예시로 설명하고자 한다.

생성자를 이용

class BurgerChef {
    private BurgerRecipe burgerRecipe;

    public BurgerChef(BurgerRecipe burgerRecipe) {
        this.burgerRecipe = burgerRecipe;
    }
}

class BurgerRestaurantOwner {
    private BurgerChef burgerChef = new BurgerChef(new HamburgerRecipe());

    public void changeMenu() {
        burgerChef = new BurgerChef(new CheeseBurgerRecipe());
    }
}

메소드를 이용 (대표적으로 Setter 메소드)

class BurgerChef {
    private BurgerRecipe burgerRecipe = new HamburgerRecipe();

    public void setBurgerRecipe(BurgerRecipe burgerRecipe) {
        this.burgerRecipe = burgerRecipe;
    }
}

class BurgerRestaurantOwner {
    private BurgerChef burgerChef = new BurgerChef();

    public void changeMenu() {
        burgerChef.setBurgerRecipe(new CheeseBurgerRecipe());
    }
}

DI 장점

그렇다면, DI, 의존 관계를 분리하여, 주입을 받는 방법의 코드 구현은 어떠한 장점이 있는가?

1.의존성이 줄어든다.

  • 앞서 설명했듯이, 의존한다는 것은 그 의존대상의 변화에 취약하다는 것이다.(대상이 변화하였을 때, 이에 맞게 수정해야함) DI로 구현하게 되었을 때, 주입받는 대상이 변하더라도 그 구현 자체를 수정할 일이 없거나 줄어들게됨.

2.재사용성이 높은 코드가 된다.

  • 기존에 BurgerChef 내부에서만 사용되었던 BurgerRecipe을 별도로 구분하여 구현하면, 다른 클래스에서 재사용할 수가 있다.

3.테스트하기 좋은 코드가 된다.

  • BurgerRecipe의 테스트를 BurgerChef 테스트와 분리하여 진행할 수 있다.

4.가독성이 높아진다.

  • BurgerRecipe의 기능들을 별도로 분리하게 되어 자연스레 가동성이 높아진다.

생성자 주입을 선택하라!

  • 불변
    대부분의 의존관계 주입은 한번 일어나면 애플리케이션 종료까지 변경할 일이 없다. 오히려 변하면 안된다.
    수정자 주입을 사용하면 setXxx()메서드를 public으로 열어두어야 한다.
    누군가 실수로 변경할 수 도 있고, 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다.
  • 누락
profile
자바 스터디 정리 - 하단 홈 버튼 참조.

0개의 댓글