목차
728x90

문제 개요
Spring Boot Application Initialize 후 의존성 주입 과정에서 순환참조 문제가 발생했다.

원인 분석
Bean 생성 과정에서 상호 의존성을 주입하는 과정에서 순환참조 문제가 발생했음.
문제의 코드
java
닫기@Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { private final Rq rq; // JwtAuthFilter → memberService 의존 private final MemberService memberService; // ... }
java
닫기@Service @RequiredArgsConstructor @Transactional(readOnly = true) public class MemberService { private final MemberRepository memberRepository; // memberService → SecurityConfig.PasswordEncoder 의존 private final PasswordEncoder passwordEncoder; private final AuthTokenService authTokenService; // ... }
java
닫기@Configuration @RequiredArgsConstructor @EnableWebSecurity public class SecurityConfig { // SecurityConfig → JwtAuthFilter 의존 private final JwtAuthenticationFilter jwtAuthenticationFilter; @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // ... } @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
IOC 컨테이너는 빈 생성 과정에서 모든 빈 오브젝트를 싱글톤으로 만들게 되는데,
이 과정에서 싱글톤으로 만들어진 빈 오브젝트가 우로보로스마냥 서로를 호출해서 문제가 발생함.
이렇게 서로를 꼬리물듯이 의존성을 주입하게 되면 스프링 IOC 컨테이너는 어떤 스프링 빈을 기준으로 먼저 생성하고 의존성을 주입할지 결정할 수 없는 문제가 발생한다.
해결 방법
문제의 빈 객체를 다른 클래스로 이동 (해결)
java
닫기@Configuration @RequiredArgsConstructor public class AppConfig { @Bean // 기존 SecurityConfig → AppConfig으로 이동 public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
순환참조 구조를 해소할 수 있게끔 순환참조 문제의 빈 컨텍스트를 다른 클래스로 이동시켰다.
따라서 개선된 구조는 아래와 같이 순환참조 문제를 해결하였다.
- 기존 : JwtAuthFilter → MemberService → SecurityConfig → JwtAuthFilter → ...
- 개선 : AppConfig → MemberService → SecurityConfig → JwtAuthFilter
@Lazy를 사용하는 방법 (권장되지 않음 / 대안)
Lazy를 사용하면 프록시 객체를 통해 Bean을 생성하며, 필요 시점에 호출하여 빈을 생성한다.
이는 단순히 잘못된 구조에서 Bean 생성시점을 늦출 뿐이기에 근본적인 해결책이 되지 못한다.
기존에 의존성 구조를 구성할 때 순환참조가 발생하지 않게 짜는 것이 좋다.

'DEV > Spring' 카테고리의 다른 글
SecurityConfig Spring Method Security 적용하기 (0) | 2024.02.20 |
---|---|
[트러블슈팅] Spring ApplicationRunner RuntimeException 발생 시 shutdown되는 오류 해결 (0) | 2024.02.20 |
[트러블슈팅] .sql 파일 init이 자동으로 실행되지 않는 문제 원인 / 해결방법 (0) | 2024.02.20 |
[트러블슈팅][JPA] OneToOne 양방향 관계 시 의도하지 않은 N+1 문제 발생 원인과 해결 방법 (0) | 2024.02.20 |
[트러블슈팅] @ReqestParam, @PathVariable 사용 시 Name for argument of type [”type”] not specified 에러 해결 (0) | 2024.02.19 |