Spring에서 순환 참조가 발생하는 이유와 해결 방법을 설명해주세요.
답변 포인트
A Bean이 B를 필요로 하고 B Bean도 A를 필요로 하는 구조를 생각해보세요.
정답 및 해설
빠른 요약
Spring의 순환 참조는 Bean A가 Bean B를 의존하고, 동시에 Bean B도 Bean A를 의존할 때 발생합니다. 생성자 주입에서는 두 객체를 만들기 위해 서로가 먼저 필요하므로 컨테이너가 인스턴스를 완성할 수 없습니다.
Spring의 순환 참조는 Bean A가 Bean B를 의존하고, 동시에 Bean B도 Bean A를 의존할 때 발생합니다. 생성자 주입에서는 두 객체를 만들기 위해 서로가 먼저 필요하므로 컨테이너가 인스턴스를 완성할 수 없습니다.
@Service
class OrderService {
OrderService(PaymentService paymentService) {}
}
@Service
class PaymentService {
PaymentService(OrderService orderService) {}
}예전에는 setter 주입이나 필드 주입에서 일부 순환 참조가 허용되기도 했지만, 이는 설계 냄새를 숨길 수 있습니다. 최근 Spring Boot에서는 순환 참조를 기본적으로 더 엄격히 다루는 방향입니다.
가장 좋은 해결책은 책임을 다시 나누는 것입니다. 두 서비스가 서로를 알아야 한다면 공통 로직을 별도 컴포넌트로 분리하거나, 이벤트 발행으로 직접 의존을 끊을 수 있습니다. 예를 들어 주문 완료 후 결제 후속 작업은 OrderCompletedEvent를 발행하고 listener가 처리하게 할 수 있습니다.
임시 방편으로 @Lazy를 사용해 한쪽 의존성을 지연 주입할 수 있지만, 구조적 문제를 해결하는 것은 아닙니다. 면접에서는 “순환 참조는 DI 문제가 아니라 책임 경계가 흐려졌다는 신호”라고 말하면 좋습니다.