늦은 프로그래밍 이야기
DI (의존성 주입) 본문
DI란?
- DI는 Dependency Injection의 줄임말
- 의존성 주입, 의존관계 주입
Dependency (의존관계)
“A가 B를 의존한다”는 표현의 의미
- 의존대상 B가 변하면, 그것이 A에 영향을 미친다.
- 즉, B의 기능이 추가 또는 변경되거나 형식이 바뀌면 그 영향이 A에 미친다.
햄버거 가게 예시
- 햄버거 가게 요리사는 햄버거 레시피에 의존한다.
- 햄버거 레시피가 변화하게 되었을 때, 변화된 레시피에 따라 요리사는 햄버거를 만드는 방법을 수정해야 한다.
- 레시피의 변화가 요리사의 행위에 영향을 미쳤기 때문에, “요리사는 레시피에 의존한다”고 말할 수 있다.
- 코드로 표현
class BurgerChef {
private HamBurgerRecipe hamBurgerRecipe;
public BurgerChef() {
hamBurgerRecipe = 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 new Burger() {
return new HamBurger();
}
// ...
}
- 의존관계를 인터페이스로 추상화하게 되면, 더 다양한 의존관계를 맺을 수 있고, 실제 구현 클래스와의 관계가 느슨해지고, 결합도가 낮아진다.
Dependency Injection
- 지금까지의 구현에서는 BurgerChef 내부적으로 의존관계인 BurgerRecipe가 어떤 값을 가질지 직접 정하고 있다.
- 만약 어떤 BurgerRecipe를 만들지를 버거 가게 사장님이 정하는 상황을 가정한다.
- 즉, BurgerChef가 의존하고 있는 BurgerRecipe를 외부(사장님)에서 결정하고 주입하는 것이다.
- 이처럼 그 의존관계를 외부에서 결정하고 주입하는 것이 DI(의존관계 주입)이다.
- 다음의 3가지 조건을 충족하는 작업을 의존관계 주입이라 말한다.
- 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스만 의존하고 있어야 한다.
- 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제 3의 존재가 결정한다.
- 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
DI 구현 방법
- DI는 의존관계를 외부에서 결정하는 것이기 때문에 클래스 변수를 결정하는 방법들이 곧 DI를 구현하는 방법이다.
- 런타임 시점의 의존관계를 외부에서 주입하여 DI 구현이 완성된다.
- 생성자를 이용
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 BuergerChef(); public void changeMenu() { burgerChef.setBurgerRecipe(new CheeseBurgerRecipe()); } }
DI 장점
- 의존성이 줄어든다.
- 앞서 설명했듯이, 의존한다는 것은 그 의존대상의 변화에 취약하다는 것이다. (대상이 변화하였을 때, 이에 맞게 수정해야함) DI로 구현하게 되었을 때, 주입받는 대상이 변하더라도 그 구현 자체를 수정할 일이 없거나 줄어들게 된다.
- 재사용성이 높은 코드가 된다.
- 기존에 BurgerChef 내부에서만 사용되었던 BurgerRecipe를 별도로 구분하여 구현하면, 다른 클래스에서 재사용할 수가 있다.
- 테스트하기 좋은 코드가 된다.
- BurgerRecipe의 테스트를 BurgerChef 테스트와 분리하여 진행할 수 있다.
- 가독성이 높아진다.
- BurgerRecipe의 기능들을 별도로 분리하게 되어 자연스레 가독성이 높아진다.
출처 :
의존관계 주입(Dependency Injection) 쉽게 이해하기
의존관계 주입(Dependency Injection) 쉽게 이해하기
이번 글에서는 DI(의존성 주입, 의존관계 주입)의 개념을 설명한다.
tecoble.techcourse.co.kr
'내일배움캠프 > Spring' 카테고리의 다른 글
| POJO (0) | 2022.12.23 |
|---|---|
| IoC 컨테이너 (0) | 2022.12.21 |
| Annotation (1) | 2022.12.21 |
| UnsatisfiedDependencyException 에러 해결 (0) | 2022.12.16 |
| Spring MVC (0) | 2022.12.07 |
Comments