본문 바로가기
spring_boot/Error

[Spring Security - kotlin] Spring Bean 순환 참조 에러_Relying upon circular references is discouraged and they are prohibited by default.

by 잡다한 개발자 정모씨 2024. 5. 7.

들어가며

spring security에 대한 개발을 어느정도 완료하고 실행하며 테스트하는 도중에 Spring Bean에 대한 순환 참조에 대해 오류가 났다. 이 문제 상황을 Spring Bean에 대해 공부하며 정리할려고 한다. 글을 읽기 전에 Spring Bean에 대해 조금 알아오시는 걸 추천합니다

 

문제 상황

application을 실행해 봤는데 이런 오류가 나타났다. 

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  securityConfig defined in file [C:\Users\sun\IdeaProjects\authentication_example_kotlin-base\GB\out\production\classes\com\gachi\gb\auth\config\SecurityConfig.class]
↑     ↓
|  idPasswordAuthProvider defined in file [C:\Users\sun\IdeaProjects\authentication_example_kotlin-base\GB\out\production\classes\com\gachi\gb\auth\security\authentication\provider\IdPasswordAuthProvider.class]
└─────┘

Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

설명: 

애플리케이션 컨텍스트에서 일부 빈의 종속성은 사이클을 형성합니다: 

┌─────┐
|  securityConfig defined in file [C:\Users\sun\IdeaProjects\authentication_example_kotlin-base\GB\out\production\classes\com\gachi\gb\auth\config\SecurityConfig.class]
↑     ↓
|  idPasswordAuthProvider defined in file [C:\Users\sun\IdeaProjects\authentication_example_kotlin-base\GB\out\production\classes\com\gachi\gb\auth\security\authentication\provider\IdPasswordAuthProvider.class]
└─────┘

조치:
순환 참조에 의존하는 것은 권장되지 않으며 기본적으로 금지되어 있습니다. 애플리케이션을 업데이트하여 빈 간의 종속성 주기를 제거하세요. 최후의 수단으로 spring.main.allow-circular-references를 true로 설정하여 주기를 자동으로 중단할 수 있습니다.

 

즉 현재 securityConfig와 IdPasswordAuthProvider에서 순환참조가 일어나고 있다. 이때 이 둘의 공통점은 PasswordEncoder를 사용한다는 점이다. 그럼 생성자 주입방식의 순환참조라고 생각할 수 있다. 

 

생성자 주입방식의 순환 참조 문제

이것을 이해하기 전에 생성자 주입 방식에 대해서 알아야 한다.

 

생성자 주입 방식이란?

스프링이 실행되는 시점에 A_class가 B_class를 의존하고 B_class가 C_class 의존한다면? spring에서는 A가 B를 의존하려고 하는데 B가 생성이 안되었으니까 B 에 Bean을 주입하게 되는데 B는 C를 의존하니 C의 Bean을 먼저 만들고 B의 Bean, A의 Bean 순으로 Bean을 생성하게 된다.

 

그럼 이제 원문으로 와서 위의 생성자 주입방식을 서로한다고 생각하면 된다. 처음은 A가 B를 의존하니 B를 생성해주다가 B가 A를 의존하니 A를 생성해야되고 그것이 무한루프를 돌아 어떠한 Bean도 생성하지 못하는 것을 바로 순환참조문제 라고 한다.

 

해결 방안

이런 경우 annotation인 @Lazy를 통해서 끊는게 일시적으로 간편하지만 spring을 비롯한 개발 설계에서는 순환 참조 문제가 발생할 수 있는 구조를 만들지 않는 것이 가장 좋다고 하지만 순환 참조를 해결할 수 있는 구조는 프로젝트를 끝나고 코드 리뷰하고 refactoring할때 구조를 짜봐야 겠다. 그래서 나는 우선 아래 사진과 같이 Lazy를 사용해 참조 에러를 끊어 냈다.