[Spring] Spring Bean 순환 참조 오류
AOP 관련 실습을 해보기 위해서 Component Scan방식을 활용하여 아래와 같이 Spring Config에 AOP 객체를 추가하였다.
그리고 프로젝트를 빌드하여 실행하였는데 아래와 같은 오류가 발생하였다.
이러한 오류는 스프링 빈 순환참조(Circular dependencies) 때문에 생기는 것이다.
스프링 빈 순환참조 오류란 스프링 document에서 내용을 확인할 수 있다.
Core Technologies
In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do
docs.spring.io

내용을 번역하면 아래와 같다.
순환 종속성은 주로 생성자 주입을 사용하는 경우 해결할 수 없는 순환 종속성 시나리오를 만들 수 있습니다.
예: 클래스 A는 생성자 주입을 통해 클래스 B의 인스턴스가 필요하고 클래스 B는 생성자 주입을 통해 클래스 A의 인스턴스가 필요하다. 클래스 A와 B의 빈을 서로 주입하도록 구성하면 Spring IoC 컨테이너는 런타임에 이 순환 참조를 감지하고 BeanCurrentlyInCreationException을 발생시킨다.
한 가지 가능한 솔루션은 생성자가 아닌 설정자에 의해 구성되도록 일부 클래스의 소스 코드를 편집하는 것이다. 대안으로는 생성자 주입을 피하고 setter 주입을 사용하면 된다. 즉, 권장하지는 않지만 setter 주입으로 순환 종속성을 구성할 수 있다는 뜻이다.
순환 종속성이 없는 일반적인 경우와 달리 빈 A와 빈 B 사이의 순환 종속성은 자체적으로 완전히 초기화되기 전에 빈 중 하나가 다른 빈에 주입되도록 합니다(고전적인 닭과 달걀 시나리오).
쉽게 말하자면 A라는 클래스에서 B라는 클래스를 인스턴트로 필요로하고, B라는 클래스에서도 A라는 클래스를 인스턴트로 필요한 경우 서로가 서로를 참조하게 되면서 에러가 발생하는 것이다.
위 코드의 경우를 다시 살펴보면
@Bean//component scan으로 해도 되지만 직관적으로 보기 위해서 추가
public TimeTraceAop timeTraceAop(){
return new TimeTraceAop();
}
이렇게 Bean에서 TimeTraceAop을 선언했고, TimeTraceAop의 코드로 가보게 되면 아래와 같이 Around의 범위에서 또 TimeTraceAop를 AOP로 처리하게 되어있다.
@Aspect
public class TimeTraceAop {
@Around("execution(* com.example.demo..*(..))")
...
그렇기 때문에 AOP로 계속적으로 TimeTraceAop의 코드를 불러오기 때문에 순환참조 문제가 발생한다고 볼 수 있다.
이러한 점을 해결하기 위해서는 Component Scan방식으로 직접 TimeTraceAop를 등록해주는 방법이 있고, Around의 범위에서 SpringConfig를 제외시켜주는 방법이 있다.