HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
♥️
2기 최종 프로젝트 팀별 공간
/
🌳
[팀 05] Forest
/
🪐
BE WorkSpace
/
🛺
OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration 순환 참조 현상
🛺

OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration 순환 참조 현상

분류
OAuth2
Configuration
담당자
┌─────┐ | webSecurityConfigure ↑ ↓ | org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration ↑ ↓ | org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration └─────┘
위와 같은 오류가 발생했다.
 
Spring 2.6이후부터는 순환참조가 되지 않기 때문에 yml파일에서 순환참조를 허락하도록 바꿔줘야 한다.
 

임시 해결책 - Bob

 
💡
OAuth 관련 커스텀 객체들을 Bean이 아니라 직접 생성하도록 합니다.
 

예상 원인

SpringSecurity가 초기화 될 때 기본적인 OAuth 설정을 구성하게 되는데, 이 때 OAuth 관련 Bean들을 등록하는 로직도 실행되는 것 같습니다. 하지만 저희가 직접 관련 객체들을 @Bean 선언을 할 경우, 기본적으로 생성하도록 예약되어 있던 Bean들을 저희가 가로채서 초기화 흐름을 바꾸게 되어 순환 참조가 일어나는 것 같아요. 특히 OAuth Bean들은 의존 관계가 복잡해서 이런 현상이 발생하는 것 같습니다.
그래서 맨 아래에 작성된 저희만의 OAuth 설정 코드가 있는 Configure 메서드가 실행되기도 전에 스프링이 종료됩니다. 즉 설정 코드 문제는 아닙니다.
 
그런데 저희는 SpringSecurity가 만든 OAuth 객체와 설정들을 그대로 사용하지 않을 것이므로,
  1. 일단, ApplicationContext 초기화 과정에서 SpringSecurity가 자동으로 bean들을 등록하도록 만듭니다.
  1. 커스텀 객체들을 Bean이 아닌 수동으로 등록하도록 코드를 변경합니다. 이 중 커스텀 객체들이 의존하는 Bean들은 Autowired가 아닌 applicationContext에서 빼오는 방식으로 변경합니다. 이는 아래의 객체 생성 메서드들이 스프링의 Bean 초기화가 전부 끝난 시점에 실행되기 때문에 가능합니다.
    1. WebSecurityConfigure의 OAuth 전용 객체들(@Bean 제거)
@Configuration @EnableWebSecurity @Slf4j public class WebSecurityConfigure extends WebSecurityConfigurerAdapter { public JwtAuthenticationFilter jwtAuthenticationFilter() { return new JwtAuthenticationFilter(jwtConfigure.getHeader(), jwt()); } public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() { return new HttpCookieOAuth2AuthorizationRequestRepository(); } public OAuth2AuthorizedClientService authorizedClientService( ) { JdbcOperations jdbcOperations = getApplicationContext().getBean(JdbcOperations.class); ClientRegistrationRepository clientRegistrationRepository = getApplicationContext().getBean( ClientRegistrationRepository.class); return new JdbcOAuth2AuthorizedClientService(jdbcOperations, clientRegistrationRepository); } public OAuth2AuthorizedClientRepository authorizedClientRepository() { return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService()); } public OAuth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler() { return new OAuth2AuthenticationSuccessHandler(jwt(), getApplicationContext().getBean(UserService.class)); }
  1. 객체 초기화가 끝나고 실행되는 configure 메서드에서는 위의 객체들을 bean이 아닌 직접 생성해서 OAuth2 설정에 등록시킵니다.
 
WebSecurityConfigure의 Configure
@Override protected void configure(HttpSecurity http) throws Exception { http /** * 중간 생략 */ .oauth2Login() .authorizationEndpoint() .authorizationRequestRepository(authorizationRequestRepository()) .and() .successHandler(oauth2AuthenticationSuccessHandler()) .authorizedClientService(authorizedClientService()) .authorizedClientRepository( authorizedClientRepository()) .and() ; }