망나니 개발자님의 티스토리 블로그 글을 읽고 정리하였습니다.


생성자 주입 (Constructor Injection)

생성자 주입은 생성자를 통해서 의존성을 주입하는 방법이다. "생성자의 호출 시점에 1회" 호출되는 것이 보장된다. 따라서 주입 받은 객체가 변하지 않거나, 반드시 객체의 주입이 필요한 경우에 이를 강제할 수 있다. Spring 팀에서는 생성자 주입 방식을 추천하고 있다.

 

수정자 주입 (Setter Injection)

수정자 주입은 필드 값을 변경하는 setter를 통해서 의존 관계를 주입하는 방법이다. Setter 주입은 주입 받은 객체가 변할 가능성이 있을 때 사용한다. (그러나, 주입 받은 객체가 변하는 경우는 극히 드물다.)

 

필드 주입 (Field Injection)

필드 주입은 필드에 바로 의존 관계를 주입하는 방법이다. 필드 주입은 외부에서 변경이 불가능해서 DI프레임워크가 존재해야한다는 것과 immutable한 객체를 만들 수 없다는 단점이 존재한다. 따라서 필드 주입은 사용하지 않게 되었다.

 

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

  1. 객체의 불변성 확보
    • 실제 개발에서 객체의 의존 관계 주입의 변경이 필요한 경우는 거의 없다.
    • 수정자 주입의 경우 불필요하게 수정의 가능성을 열어두게 된다. -> OCP(개방-폐쇄 원칙)에 위배된다.
    • 따라서 생성자 주입을 통해 변경의 가능성을 배제하고 불변성을 보장하는 것이 좋다.
  2. 테스트 코드의 작성
    • 순수한 자바 코드로 단위 테스트를 작성하는 것이 가능하다. 필드 주입은 불가능하다.
  3. final 키워드 작성 및 Lombok 과의 결합
    • 생성자 주입을 사용하면 필드 객체에 final 키워드를 사용할 수 있으며, 컴파일 시점에 누락된 의존성을 확인할 수 있다. 생성자 주입을 제외한 다른 주입 방법들은 객체의 생성 이후에 호출되므로 final 키워드를 사용할 수 없다.
    • final 키워드를 붙임으로써 Lombok과 결합되어 코드를 간결하게 작성할 수 있다.
      • @RequiredArgsConstructor는 final 변수를 위한 생성자를 대신 생성해준다.
  4. 순환 참조 방지
    • 객체 A가 B를 참조하고 객체 B가 A를 참조하는 상황
      • 서로 주거니 받거니 호출을 끊임없이 반복할 것이고, 메모리에 함수의 callStack이 쌓여 StackOverFlowError를 발생 시킨다.
    • 애플리케이션 구동 시점(즉 객체가 생성되는 시점)에 순환 참조 에러가 발생한다.
    • 다른 주입 방식의 경우 객체 생성 시점에는 순환 참조를 발견할 수 없다. 결국 비즈니스 로직 상에서 순환 참조가 발생할 수 있다.
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기