Dependency Injection (의존성 주입)?

imyulm·2022년 11월 13일
0

스프링 공부

목록 보기
2/2
post-thumbnail

Dependency

Dependency?

의존대상 B가 변하면, 그것이 A에 영향을 미친다.
-- 이일민, 토비의 스프링 3.1, 에이콘(2012), p113

Dependency 추상화

버거 셰프, 햄버거 레시피 관계로 Dependency 추상화 개념을 알아보자.

class BurgerChef {
    private HamBurgerRecipe hamBurgerRecipe;

    public BurgerChef() {
        hamBurgerRecipe = new HamBurgerRecipe();        
    }
}

버거 셰프가 만들어야할 햄버거 레시피는 버거 셰프 생성자에 의해 자동으로 HamBurgerRecipe가 된다.
이 때, 버거 셰프는 햄버거 레시피에 의존한다.
다른 햄버거 레시피를 갖고 싶다면 new HamBurgerRecipe를 다른 햄버거 레시피로 하나하나 바꿔주어야 한다.
이 때, dependency interface 추상화가 필요하다.
예시로 설명하자면, 아래의 코드처럼 HamBurgerRecipe 타입 대신 여러 햄버거 레시피를 받을 수 있는 타입으로 interface를 생성해준 뒤 여러 햄버거 레시피를 받으면 된다.

class BurgerChef {
    private BurgerRecipe burgerRecipe;

    public BurgerChef() {
        burgerRecipe = new HamBurgerRecipe();
        //burgerRecipe = new CheeseBurgerRecipe();
        //burgerRecipe = new ChickenBurgerRecipe();
    }
}

interface BugerRecipe {
    newBurger();
    // 이외의 다양한 메소드
} 

class HamBurgerRecipe implements BurgerRecipe {
    public Burger newBurger() {
        return new HamBerger();
    }
    // ...
}

BurgerRecipe로 inerface를 생성해 준 뒤, 여러 버거레시피를 BurgerRecipe를 implements하면서 다양하게 받을 수 있게 되었다.
하지만 레시피를 바꿀때마다 직접 버거 셰프 생성자를 수정해주어야 한다.
이 때, 의존성 주입이 등장한다.

Dependency Injection

: 의존 관계를 의존하고 있는 것들 내부에서 결정하는 것이 아니라 외부에서 결정하도록 하는 것

버거 셰프와 햄버거 레시피의 의존을 결정하는 햄버거 가게 주인이 의존성을 주입하는 주체가 된다.

  1. 생성자 이용
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());
    }
}

BurgerChef 생성자의 인자로 BurgerRecipe가 생긴 것을 알 수 있다.
이 BurgerRecipe는 햄버거 가게 주인에 의해 BurgerChef를 new하면서 인자로 HamBurgerRecipe를 주입한다.
따라서 BurgerChef는 생성자의 인자로 HamBurgerRecipe를 받게 된다는 말이 된다.
이렇게 직접 생성자에 주입해주는 방법이 있다.

  1. 메소드 이용 (ex. 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());
    }
}

이번에는 햄버거 가게 주인이 BurgerChef에게 처음에는 HamburgerRecipe가 디폴트로 주어진다.
이 후, setBurgerRecipe라는 메소드를 사용해서 나중에 CheeseBurgerRecipe를 주입해준다.

Dependency의 조건

  • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스만 의존하고 있어야 한다.
  • 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.
  • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
    -- 이일민, 토비의 스프링 3.1, 에이콘(2012), p114

DI (의존성 주입) 의 장점

  1. 의존성이 줄어든다.
  2. 재사용성이 높은 코드가 된다.
  3. 테스트하기 좋은 코드가 된다.
  4. 가독성이 높아진다.

DI (의존성 주입) 의 단점

  1. 코드 추적 어려움
  2. 빌드 시간 증가

요약

DI는 의존하는 객체를 외부에서 선언하고 주입하여 사용하는 것

profile
Junior programmer 궁금 해결

0개의 댓글