Spring - 의존성 주입(DI)을 '생성자 주입 방식'으로 권장하는 이유

728x90

필드 주입 방식으로 의존성을 주입하는 방식에 익숙한(?) 개발자도 있을 것이다. 하지만 스프링에서 필드 주입 방식은 선호하지 않는다.

필드 주입 방식을 선호하지 않는다고 한다.

그렇다면 스프링은 어떤 방식을 선호할까? 퀵 액션(맥 기준 ⌥ + ↩︎) 버튼을 누르면 아래와 같이 나타난다.

그 결과는 생성자 주입방식으로 변경해준다. 그 내용을 더 상세히보면

처음 언급했던 것 처럼, Spring Team은 의존성 주입은 항상 생성자를 사용하라고 하고있다.

의존성 주입 방식은 아래와 같이 3가지가 있다.

  • 생성자 주입 (권장)
  • 설정자 주입 (Setter Injection)
  • 필드 주입 (@Autowired 선언)

그렇다면 이 3가지의 의존성 주입 방식 중에서 생성자 주입 방식을 사용함으로써 얻을 수 있는 이점은 무엇일까?

    1. 단일 책임의 원칙
      생성자의 인자가 많을 경우 코드량도 많아지고, 의존관계도 많아져 단일 책임의 원칙에 위배된다. 그래서 생성자 주입 방식을 사용함으로써 의존관계, 복잡성을 쉽게 알수 있어 리팩토링의 실마리를 제공한다
    1. 테스트 용이성
      DI컨테이너에서 관리되는 클래스는 특정 DI 컨테이너에 의존하지않고 POJO여야 한다. DI 컨테이너를 사용하지 않고도 인스턴스화 할 수 있고, 단위 테스트도 가능하며, 다른 DI 프레임 워크로 전환할 수도 있게 된다.
    1. Immutability
      생성자 주입에서는 필드는 final로 선언할 수 있다(위에서도 자동으로 final 변수로 선언했다). 불변 객체가 가능한데 비해 '필드 주입' 방식은 final을 선언할 수 없기 때문에 객체가 변경 가능한 상태가 된다.
    1. 순환 의존성
      생성자 주입에서는 멤버 객체가 순환 의존성을 가질 경우 BeanCurrentlyIncreationException() 이 발생해서 순환 의존성을 알 수 있게 된다.
    1. 의존성 명시
      의존 객체 중 필수는 생성자 주입을 옵션인 경우는 Setter Injection을 활용할 수 있다.

글을 끝마치며...

필자 같은 경우 스프링을 사용할 때, 생성자 주입방식을 적극적으로 사용하고 있는데 이러한 장점들을 정확히 알고 사용했다기보다는 '스프링이 권장하는 방식'이라는 것 때문에 맹목적으로 사용했는데 이러한 특징을 알고 사용하는 것이 중요하다 생각하여 왜? 사용하지라는 의문이 들었다. 누군가 왜 의존성 주입을 생성자 주입 방식을 사용하나요? 라고 했을 때, 근사하게 설명할 수 있지 않을까?


참고자료

스프링부트를 이용한 웹 서비스 개발 T아카데미
왜 Constructor Injection을 사용해야 하는가?

728x90