본문 바로가기
springboot

[springboot] 스프링에서 Bean 주입 시 @Autowired 사용을 권장하지 않는 이유

by 개발LOG 2024. 2. 15.

Spring에서 관리하는 Bean 객체 주입 방법에는 3가지가 있다. (Controller, Service에서 DI 발생)

  • @Autowired
  • setter
  • 생성자

이 중 가장 권장하는 방식은 생성자로 주입받는 방식이다.(@Autowired는 권장하지 않는다.) 즉, 생성자로 Bean 객체를 받도록하면 @Autowired와 동일한 효과를 볼 수 있다. 생성자는 @RequiredArgsConstructorfinal이 선언된 모든 필드를 인자값으로 하는 생성자를 롬복의  @RequiredArgsConstructor가 대신 해준다.

 

(생성자를 직접 안 쓰고 롬복 어노테이션을 사용하는 이유는 해당 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속해서 수정하는 번거로움을 해결하기 위함이다. @RequiredArgsConstructor가 있다면 해당 컨트롤러에 새로운 서비스를 추가하거나, 기존 컴포넌트를 제거하는 등의 상황이 발생해도 생성자 코드는 전혀 손대지 않아도 되니까 편리하기 때문이다.)


그럼 왜 @Autowired  사용을 권장하지 않을까?

1.  단점

순환 참조가 발생할 수 있음. 순환 참조가 발생할 경우, 컴파일 타임 시 에러가 잡히지 않다가 로직이 실행되는 런타임 시에 에러가 잡힘. 컴파일 때 에러가 잡히지 않으니, 애플리케이션이 정상적으로 작동하는 것 보임. setter 주입이나 생성자 주입의 경우에는 컴파일 타임 때 에러가 잡히므로, 문제가 되는 부분을 즉각적으로 파악할 수 있음.

 

2. @Autowired 를 적용한 필드 주입 방식보다는 생성자 주입 방식을 왜 선택해야 하는지

세 가지 이유가 있음.

  1. 불변 ( immutable )
    • 생성자 주입은 객체를 생성할 시 딱 한번만 호출되므로, 이후 의존관계를 변경할 일이 없으며 변경의 여지를 만들지 않음.
  2. 누락 
    • 순수 자바 테스트에서 의존 관계를 누락한 경우, 생성자 주입은 컴파일 오류가 발생. setter 주입의 경우 런타임 시 에러. 필드 주입의 경우에는 아예 불가능(외부 라이브러리에 테스트를 의존해야 함)
  3. final 키워드 사용 유무
    • 생성자 주입의 경우 final 키워드 사용 가능. 그래서, 혹시라도 값이 설정되지 않는 경우 즉각적으로 컴파일 오류를 뱉어냄.

정리하면,

  • 순환 참조를 방지할 수 있다.
    • 순환 참조가 발생하는 경우 애플리케이션이 구동되지 않는다.
  • 테스트 코드 작성이 편리하다.
    • 단순 POJO를 이용한 테스트 코드를 만들 수 있다.
  • 나쁜 냄새를 없앤다.
    • 조금 더 품질 좋은 코드를 만들 수 있다.
  • immutable 하다.
    • 실행 중에 객체가 변하는 것을 막을 수 있다.
    • 오류를 사전에 방지할 수 있다.