Spring DI(Dependency Injection, 의존성 주입)

의존성이란?

객체를 생성 및 사용함에 있어서 의존관계에 있는 경우를 말한다. 간단한 예제를 통해 알아보자.

스프링에서 DI 문법 3가지

필드 주입

  • 스프링 @Autowired를 이용하여 객체 내부에 필드에 선언하여 주입하는 방식이다.
  • 간편하지만 참조 관계를 눈으로 확인하기 어렵다.
  • 남발하게 되면 참조 관계가 꼬일 수 있다.
public class Foo {
    @Autowired
    private Bar bar;
}

필드 주입 장점

  • 코드 간결

필드 주입 단점

  • unit test가 어렵다.
  • final 선언이 불가능하다.
  • 순환 의존성이 발생한 경우 디텍트 하지 못한다. (순환 의존성: A -> B, B-> A)

Setter 주입

  • 스프링 @Autowired를 이용하여 Setter 메소드를 통해서 주입 방식이다.
  • Null Pointer Exception이 발생할 수 있다.
public class Foo {
    private Bar bar;

    @Autowired
    public void setBar (Bar bar) {
        this.bar = bar;
    }
}

생성자 주입

  • final 필수로 생성자를 통해서 주입되는 방식이다.
  • 필드 주입과 다르게 참조 관계를 눈으로 쉽게 확인할 수 있다.
  • 초기에 생성에 할당이 되어야 하기에 Null Pointer Exception이 절대 발생하지 않는다.
public class Foo {
    private final Bar bar;

    @Autowired
    public Foo(Bar bar) {
        this.bar = bar;
    }
}

생성자 주입 사용시 장점

  • 순환 참조 방지
    • 순환 참조는 A가 B를 참조하고, B가 A를 참조하는 경우에 발생하는 문제이다.
    • 생성자 주입은 먼저 빈을 생성하지 않고 주입하려는 빈을 찾는다. 그래서 어플리케이션 기동시에 에러가 발생하여 금방 문제를 찾을 수 있다.
  • final 선언이 가능
    • 생성자 주입 시, 의존성 주입이 클래스 인스턴스화 중에 시작되므로 final을 선언할 수 있다. 따라서 객체를 변경이 불가능하게 할 수 있다.
  • 단위 테스트 코드 작성 용이
    • 스프링 컨테이너 도움 없이 테스트 코드를 더 편리하게 작성할 수 있다.

스프링에서의 DI

명세서에 따라 자동으로 부품을 조립하는 것과 비슷하다

  • 프로그래머가 하는 일
    • 부품을 만든다 (클래스 구현) š - 부품 조립 명세서 정의 (생성자 주입 방식 추천 )
  • 스프링 프레임워크가 하는 일
    • 부품을 조립한다. (자동으로 DI를 해준다. 즉 생성자/setter를 자동으로 호출해준다)
    • 쓸 줄 아는 “제품”은 알아서 사용한다.
      • 예: 특정 URL에 대한 request가 도착하면 해당 request에 대한 처리 로직을(Controlle) 자동으로 호출해 준다.