반응형

스프링에는 3가지 빈 주입을 제공한다.

필드 주입, 수정자 주입, 생성자 주입이다.
대부분 스프링을 한다면, 알고 있는 내용일 것이다. 하지만 조금 더 알아 보자.

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


필드 주입

  • 장점

    • 사용하기 가장 편하다.
  • 단점

    • 순환 참조를 컴파일 타임에 알 수 없다.(스프링 부트 2.5이하)

      • 런타임에 로직 호출 시에 알 수 있다. 컴파일 시점에는 각자 주입만할 뿐
        누가 자신을 사용하고 있는지는 알지 못하기 때문이다.
      • 하지만 2.6이상 부터는 이를 개선하여 컴파일 타임에 알 수 있다.
    • 객체를 바꿀 수 없다. 즉, 테스트 할 때 불편하다.

수정자 주입

  • 장점
    • 객체를 바꿀 수 있다. 즉, 테스트 할 때 편하다.
  • 단점
    • 순환 참조를 컴파일 타임에 알 수 없다.(스프링 부트 2.5이하)
      • 런타임에 로직 호출 시에 알 수 있다. 컴파일 시점에는 각자 주입만할 뿐
        누가 자신을 사용하고 있는지는 알지 못하기 때문이다.
      • 하지만 2.6이상 부터는 이를 개선하여 컴파일 타임에 알 수 있다.
    • final을 사용할 수 없기 때문에 중간에 객체를 바꿀 수 있는 것이 단점이 될 수도 있다.
      캡슐화가 되지 않았기 때문이다.

필드 주입과 수정자 주입의 공통적인 단점을 보면, 순환 참조이다.
순환 참조를 하게되면 아래와 같이 StackOverflowError가 발생하게 된다.
하지만, 스프링 부트 2.6이상 이거나 생성자 주입을 사용하면 애초에 방지할 수 있다.
만약 순환 참조를 허용하려면 spring.main.allow-circular-references=true로 옵션을 주면된다.
하지만, 서로 의존하고 있어도 순환 참조가 발생하는 로직을 만들지 않으면 된다.
그래도 실수라는 것이 존재하기 때문에 옵션을 true로 바꾸는 것은 신중해야 한다.
최대한 한 방향으로만 의존하도록 설계하는 것이 좋다고 생각한다.

생성자 주입

모든 단점을 개선한 것이다.

  • 장점
    • 객체를 변경할 수 있다. 즉, 테스트할 때 편하다.
    • 버전 상관없이 컴파일 시점에 순화 참조를 알 수 있다.
      빈 주입을 위해서는 주입받는 빈도 이미 생성이 완료되어야 하기 때문이다.
    • final을 사용할 수 있기 때문에 주입을 강제할 수 있고, 리플렉션 같은 공격으로 재할당도 불가하다.

스프링 부트 2.6에서 순환 참조를 기본적으로 금지한다는 공식 문서

반응형
복사했습니다!