Spring Boot3, Java17 기준이다.
🔁 전체 흐름 정리
Spring Boot 어플리케이션이 시작될 때 내부적으로 아래와 같은 과정이 진행된다.
1. @ComponentScan 동작
Spring Boot 어플리케이션을 실행했을 때 Spring Boot 메인함수에 있는 @SpringBootApplication 어노테이션에
있는 @ComponentScan 이 지정된 패키지를 탐색하면서 @Component, @Controller, @Service, @Repository 등을
가진 클래스를 찾는다.
2. Bean 등록 (객체 생성 + 의존성 주입)
- @ComponentScan 에 의해 찾은 클래스들을 스프링 컨테이너에 Bean 등록한다.
- 이때 의존성이 필요하면 생성자를 통해 주입하게 된다. (생성자 주입의 경우)
- 의존성이 필요한 Bean 이 먼저 등록되어 있어야 한다.
- 생성자에 @Autowired 를 명시하지 않아도 생성자가 하나뿐이면 자동 주입된다.
즉, Bean 생성 = 생성자 호출 = 생성자 주입 실행
객체를 생성하면서 필요한 의존성을 주입하는 구조다.
🧠 순환 참조와의 연관성
순환 참조는 언제 발생하는가?
- 두 Bean 이 서로 생성자에서 상대방을 요구하면 스프링이 첫번째 Bean 을 반들려고 하는데
두번째 Bean 이 필요하고, 두번째 Bean 을 만들려니 다시 첫번째 Bean 이 필요해서
무한 루프가 발생하게 된다.
생성자 주입은 순환 참조 허용 ❌
- 생성자 주입 방식은 순환 참조를 허용하지 않는다.
- Spring Boot 2.6 부터는 기본적으로 순환 참조를 금지하며, 이걸 풀더라도 생성자 주입은 지원하지 않는다.
🔍 예시
@Service
public class AService {
private final BService bService;
public AService(BService bService) {
this.bService = bService;
}
}
@Service
public class BService {
private final AService aService;
public BService(AService aService) {
this.aService = aService;
}
}
이 구조는 생성자 주입 시점에서 다음과 같은 문제를 발생시킨다.
- AService 를 만들려면 BService 가 필요하다.
- BService 를 만들려면 AService 가 필요하다.
- 👉 순환 참조 예외 발생
🔚 결론 요약
질문 |
답변 |
생성자 주입은 언제 발생하나요? |
Bean이 생성될 때, 즉 스프링 컨테이너에 등록될 때 함께 주입됩니다. |
Bean 등록보다 먼저 주입되나요? |
아니요. Bean 등록과 동시에 주입됩니다. |
순환 참조는 왜 문제가 되나요? |
생성자 주입은 객체를 만들면서 의존성도 즉시 요구하기 때문에, 순환이 생기면 객체를 만들 수 없게 됩니다. |