Spring에서 관리하는 Bean 객체 주입 방법에는 3가지가 있다. (Controller, Service에서 DI 발생)
- @Autowired
- setter
- 생성자
이 중 가장 권장하는 방식은 생성자로 주입받는 방식이다.(@Autowired는 권장하지 않는다.) 즉, 생성자로 Bean 객체를 받도록하면 @Autowired와 동일한 효과를 볼 수 있다. 생성자는 @RequiredArgsConstructor이 final이 선언된 모든 필드를 인자값으로 하는 생성자를 롬복의 @RequiredArgsConstructor가 대신 해준다.
(생성자를 직접 안 쓰고 롬복 어노테이션을 사용하는 이유는 해당 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속해서 수정하는 번거로움을 해결하기 위함이다. @RequiredArgsConstructor가 있다면 해당 컨트롤러에 새로운 서비스를 추가하거나, 기존 컴포넌트를 제거하는 등의 상황이 발생해도 생성자 코드는 전혀 손대지 않아도 되니까 편리하기 때문이다.)
그럼 왜 @Autowired 사용을 권장하지 않을까?
1. 단점
순환 참조가 발생할 수 있음. 순환 참조가 발생할 경우, 컴파일 타임 시 에러가 잡히지 않다가 로직이 실행되는 런타임 시에 에러가 잡힘. 컴파일 때 에러가 잡히지 않으니, 애플리케이션이 정상적으로 작동하는 것 보임. setter 주입이나 생성자 주입의 경우에는 컴파일 타임 때 에러가 잡히므로, 문제가 되는 부분을 즉각적으로 파악할 수 있음.
2. @Autowired 를 적용한 필드 주입 방식보다는 생성자 주입 방식을 왜 선택해야 하는지
세 가지 이유가 있음.
- 불변 ( immutable )
- 생성자 주입은 객체를 생성할 시 딱 한번만 호출되므로, 이후 의존관계를 변경할 일이 없으며 변경의 여지를 만들지 않음.
- 누락
- 순수 자바 테스트에서 의존 관계를 누락한 경우, 생성자 주입은 컴파일 오류가 발생. setter 주입의 경우 런타임 시 에러. 필드 주입의 경우에는 아예 불가능(외부 라이브러리에 테스트를 의존해야 함)
- final 키워드 사용 유무
- 생성자 주입의 경우 final 키워드 사용 가능. 그래서, 혹시라도 값이 설정되지 않는 경우 즉각적으로 컴파일 오류를 뱉어냄.
정리하면,
- 순환 참조를 방지할 수 있다.
- 순환 참조가 발생하는 경우 애플리케이션이 구동되지 않는다.
- 테스트 코드 작성이 편리하다.
- 단순 POJO를 이용한 테스트 코드를 만들 수 있다.
- 나쁜 냄새를 없앤다.
- 조금 더 품질 좋은 코드를 만들 수 있다.
- immutable 하다.
- 실행 중에 객체가 변하는 것을 막을 수 있다.
- 오류를 사전에 방지할 수 있다.
'springboot' 카테고리의 다른 글
[springboot] 구글 로그인 api 테스트 사용자 추가 (0) | 2024.02.18 |
---|---|
[springboot] 구글 로그인 api 연동 (0) | 2024.02.18 |
[springboot] 컨트롤러 JUnit 테스트 (0) | 2024.02.14 |
[springboot] JUnit 테스트에서 @Slf4j 사용하기 (0) | 2024.02.14 |
[토이프로젝트] h2-console mv.db 오류 해결 (0) | 2024.02.11 |