Spring

[Spring] DI 의존성 주입 방식과 생성자 주입을 사용해야 하는 이유

DEV숨 2022. 11. 22. 21:28

의존성 주입(DI)이란?

DI란, 객체 간 의존 관계를 스프링 컨테이너가 Bean등록 정보를 바탕으로 자동으로 주입해주는 기능을 말한다.

일반적으로 스프링 프로젝트를 보면, 컨트롤러에서 서비스나 레포지토리 객체를 사용 시, 컨트롤러에서 서비스나 레포지토리 객체를 사용 시 new 키워드를 통해 컨트롤러에서 직접 객체를 생성하지 않고 의존성 주입을 통해 스프링 컨테이너에 생성된 객체를 받아 사용하고 있는 것을 볼 수 있다.

위와 같은 어노테이션이 붙은 클래스들은 스프링 실행 시 스캔을 통해 개발자가 정의한 의존성 정보를 자동으로 bean 설정 정보에 등록을 하게 되어 의존성 주입이 동작하게 합니다.

이를 통해 객체간 결합도를 낮추고, 코드의 양을 줄여주고, 테스트를 용이하게 하며, 개발 및 유지보수를 더 쉽게 하는 장점이 있다.

 

 

의존성 주입 종류 

DI(의존성 주입) 종류

  • 생성자 주입
    • 생성자를 통해 의존 관계를 주입하는 방법이다.
    • 생성자 주입은 생성자의 호출 시점에 1회 호출 되는 것이 보장된다.
    • 주입받은 객체가 변하지 않거나, 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용할 수 있다.
    • 생성자 1개만 있을 경우에 @Autowired를 생략해도 주입이 가능하도록 편의성을 제공하고 있다.
  • setter 주입
    • setter를 통해서 의존 관계를 주입하는 방법이다.
    • 주입받는 객체가 변경될 가능성이 있는 경우에 사용한다.
    • @Autowired로 주입할 대상이 없는 경우에 오류가 발생한다.
  • 필드 주입(Field Injection)
    • 가장 간결한 주입 방식이다.
    • field 위에 @Autowired 어노테이션을 다는 방식이다.
    • 필드 주입은 외부에서 접근이 불가능하며 필드의 객체를 수정할 수 없다는 단점이 있다.
    • 또한 필드 주입은 반드시 DI 프레임워크가 존재해야한다.
  • 일반 메소드 주입
    • 세터 주입과 동일하다.
    • 한번에 여러 필드를 주입 받을 수 있다.

 

 

생성자 주입을 사용해야 하는 이유

  1. 객체의 불변성 확보
    • 실제로 개발을 하다 보면 의존 관계의 변경이 필요한 상황은 거의 없다.
    • 하지만 수정자 주입이나 일반 메소드 주입을 이용하면 불필요하게 객체 밖에서 수정할 수 있다.
    • 생성자 주입을 통해 불변성을 보장하는 것이 좋다.
  2. 테스트 코드 작성의 용이함
    1. 순수한 자바 코드 단위 테스트를 작성하는 것이 어렵다.
    2. 만약 필드 주입을 사용한다면, @Autowired 라는 스프링에 의존적인 어노테이션을 알아야한다.
    3. 모르고 사용한다면 NPE가 발생한다.
  3. 순환 참조 방지
    1. 객체의 생성시점 (애플리케이션 구동 시점)에 순환 참조 에러를 예방할 수 있다.
    2. A가 B를 참조하고, B가 A를 참조하는 경우 두 메서드는 서로를 계속 호출할 것이고, 메모리에 함수의 CallStack이 계속 쌓여 StackOverflow 에러가 발생하게 된다. 이러한 문제를 발견하지 못하고 서버가 운영된다면? 해당 메소드의 호출 시에 StackOverFlow 에러에 의해 서버가 죽는다. 생성자 주입 방식을 이용하면 이러한 순환 참조 문제를 방지할 수 있다.
    3. 애플리케이션 구동시점에 에러가 발생하기 때문이다!
    4. 참고로 스프링부트 2.6 버전 부터는 순환 참조가 기본적으로 허용되지 않도록 변경되었다. 필드 주입을 받아도 순환 참조가 발생한다면 컴파일 시점에 에러가 발생한다.
  4. final 키워드 작성 및 lombok과의 결합이 가능
    1. 생성자 주입을 사용하면 필드 객체에 final 키워드를 사용할 수 있다.
    2. 컴파일 시점에 누락된 의존성을 확인할 수 있다.
    3. 다른 주입 방법의 경우 객체의 생성 이후에 호출되므로 final키워드를 사용할 수 없다.
    4. final 키워드를 붙이면 lombok과 결합되어 코드를 간결하게 작성할 수 있다. @RequiredArgsConstructor

 

 

 

 

 

reference

https://dev-coco.tistory.com/70

https://mangkyu.tistory.com/125