Spring

DI(Dependency Injection)

RE.YEOL 2023. 4. 9. 10:00

의존 관계

DI 설명하기 전 의존관계를 먼저 설명하겠습니다.

의존관계 : "A가 B를 의존한다."

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

 

의존대상인 B가 변경할 때 A의 영향이 미칩니다.

현실에서 예시를 찾을 경우 "공휴일은 규정에 의존합니다."

 

1. 관공서 공휴일에 관한 규정에 따라 부처님 오신 날, 기독탄신일을 대체 공휴일로 선정하였습니다.
2. 식목일은 법 개정으로 2006년 공휴일에서 제외되었습니다.

 

이와 같이 공휴일은 규정에 의존하기 때문에 규정 변경될 때 공휴일이 생길 수도 없어질 수도 있습니다.
다음과 같이 코드로 표현할 수 있습니다.

public class Holiday{
    private  Rule rule;
    public Holiday(){
        this.rule = new Rule();
    }
}

규정이 변경될 때 다른 결과를 가져오기 때문에 큰 영향을 끼칩니다.
영향을 느슨하게 적용하기 위해 interface로 추상화해 보겠습니다.

public class Holiday{
    private  Rule rule;
    public Holiday(){
        this.rule = new RuleV1Impl();
    }
}

# Rule interface
public interface Rule{
    RuleInfo getHolidayRule();
}

# Rule Implements
public class RuleV1Impl implements Rule{
    public RuleInfo getHolidayRule(){
        ...
    }
}

지금까지는  Holiday에서 직접 new 키워드를 통해 instance를 생성하여 의존 주입하였습니다.
interface를 사용하여 결합도는 낮췄지만, 객체 지향 5원칙(SOLID)의 DIP 원칙을 위배하고 있습니다.

 

DIP(Dependency Inversion Principle)
 - 추상화(인터페이스)에 의존해야지, 구체화(구현 클래스)에 의존하면 안 된다.

 

객체 지향 5원칙은 추후 포스팅하도록 하겠습니다.

이 문제를 DI(Dependency Injection, 의존 관계 주입)를 통해 해결할 수 있습니다.
의존 관계 주입 : 외부에 의해 관계가 주입됩니다.

현실에서도 규정은 각 관할 부처에서 법을 발의하여 규정을 만들게 됩니다.

코드에서는 해당 역할을 Spring framework에서 의존 관계 주입(DI)을 해줍니다.

DI 구현방법 3가지

1. setter 주입

setter는 외부에서 쉽게 접근하여 변경가능하므로 유지보수 시 큰 문제가 생길 수 있습니다.
따라서 해당 방식에 대해 이해는 필요하지만 사용하면 안 됩니다.

public Holiday{
    private Rule rule;
    public void setHoliday(Rule rule){
        this.rule = rule;
    }
}

2. Field 주입

Spring의 @Autowired를 통하여 Fild에 의존 관계를 주입할 수 있습니다.
외부에서 접근이 불가능하여 테스트 코드 작성 시 어려움이 있기 때문에 생성자 주입 사용을 권장합니다.

@Component
public class Holiday{
    @Autowired
    private  Rule rule;
}

3. 생성자 주입

생성자를 통해 의존 관계를 주입하는 방법입니다.
Spring은 생성자 주입을 적극 지원하며, 싱글톤 방식으로 객체를 생성하기 때문에 객체가 변하지 않습니다.

@Component
public class Holiday{
    private  Rule rule;
    public Holiday(Rule rule){
        this.rule = rule;
    }

}