Dependency Injection(의존성 주입)

김대경·2022년 4월 18일
0

스프링 공부 과정

목록 보기
3/6

주의사항!

공부하며 작성한 포스트입니다. 틀린 내용이나 부실한 설명이 있다면 알려주세요.😁


DI란?

Dependency Injection. 의존성 주입 이라고도 한다.

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

  • 이일민, 토비의 스프링 3.1, 에이콘(2012), p113

즉, B의 기능이 수정된다면 A에게까지 영향을 미친다.

다음의 코드를 보며 햄버거 가게를 예시로 들어보자.


일반적인 의존관계

"햄버거 가게 요리사는 햄버거 레시피를 의존한다" 간단한 문장이다. 햄버거 레시피가 없다면, 요리사는 요리를 할 수 없고, 레시피가 수정되거나 다른 햄버거를 만들어야 한다면, 요리사는 요리 방법을 수정해야 한다. 레시피가 요리사에게 영향을 미쳤기 때문에, 요리사는 레시피에 의존한다. 라고 말할수 있다.

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

위의 코드처럼, BurgerChef는 BurgerRecipe를 의존하고있다. 더 다양한 레시피를 의존받을 수 있게 하려면, 아래 코드처럼 의존 관계를 인터페이스로 추상화 해야한다.

interface BurgerRecipe(){
	newBurger();
}

class BurgerChef {
	private BurgerRecipe burgerRecipe;
    
    public BurgerChef() {
    	this.burgerRecipe = new BurgerRecipe();
        //this.burgerRecipe = new ChickenBurgerRecipe();
        //this.burgerRecipe = new CheeseBurgerRecipe();
    }
}

class NewBurgerRecipe implements BurgerRecipe(){
	public Burger newBurger(){
    	return Hamburger();
    }
}

의존성 주입 방식

이처럼 의존성을 인터페이스로 추상화한다면 요리사는 좀 더 다양한 의존관계를 가질 수 있다.(좀 더 다양한 메뉴를 고를 수 있다) 이와같은 방법은 요리사가 햄버거 레시피를 내부적으로 정하고있는데, 만약 외부에서 메뉴를 직접 골라서 요리사에게 직접 요청(주입)한다면?
(건물주가 요리할 메뉴를 직접 고른다면?)

생성자를 사용한 DI

class BurgerChef { // 생성자를 이용한 DI
	private BurgerRecipe burgerRecipe;
    
    public BurgerChef(BurgerRecipe burgerRecipe) {
    	this.burgerRecipe = burgerRecipe;
    }
}

class BurgerShopOwner {
	private Burgerchef burgerchef = new BurgerChef(new NewBurgerRecipe());
    
    public void changeMenu(){
    	burgerchef = new BurgerChef(new CheeseBurgerRecipe());
    }
}

이처럼 코드를 작성한다면 햄버거 요리사는 햄버거 가게의 건물주가 주입해주는(결정한) 메뉴를 만들어야 한다. 이와 같은 기법을 Dependency Injection 이라고 한다. DI를 사용함으로써, 햄버거 요리사는 어떤 햄버거를 만들어야 할 지 고민할 필요가 없어졌다. 매일매일 건물주가 정해주는 메뉴를 요리만 하면 되는것이다.(관심 분리)
이 외에도 메소드(setter)를 사용한 DI, 필드주입 등, 다양한 DI방식이 있지만 Spring에서는 생성자를 이용한 방식을 권장하고 있다.

메소드를 사용한 DI

class BurgerChef { //메소드(setter)를 사용한 DI
	private BurgerRecipe burgerRecipe = new BurgerRecipe();
    public void setBurgerRecipe(BurgerRecipe burgerRecipe){
		this.burgerRecipe = burgerRecipe;
    }
}

class BurgerShopOwner {
	private Burgerchef burgerchef = new BurgerChef();
    
    public void changeMenu(){
    	burgerChef.setBurgerRecipe(new cheeseBurgerRecipe());
    }
}

장점


  1. 의존성이 줄어듦으로 인해, 주입받는 대상이 변하더라도 구현 자체를 수정할 일이 없거나 줄어들게 됨.
  2. 재사용성이 높아진다. - 기존의 BurgerChef 내부에서만 사용하던 BurgerRecipe를 다른 클래스에서 사용할 수 있게 되었다.
  3. BurgerRecipe를 BurgerChef와 분리하여 테스트 할수있게 되었다.
  4. BurgerChef와 BurgerRecipe 확장성을 높였다.

정리


  • Dependency Injection은 어떤 객체가 의존하는 또 다른 객체를 외부에서 선언, 생성하여 이를 주입받아 사용하는 것이다.
  • DI에는 여러가지 방법으로 구현할 수 있지만, 생성자를 사용한 방법을 권장하고 있다.
  • DI의 의도는 객체의 생성과 사용의 관심을 분리하는 것이다.

출처

https://tecoble.techcourse.co.kr/post/2021-04-27-dependency-injection/
https://mangkyu.tistory.com/125

profile
무언가를 개발한지 4년이 되어가는 중입니다 :) With @KSASolution

0개의 댓글