[SpirngBoot/오류] 의존성 순환(Circular Dependency) 오류 해결
Spring Boot에서 OAuth2 파트를 공부하면서 만들어 둔 프로그램을 실행시키던 중 아래와 같은 오류가 발생했다.
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| webOAuthSecurityConfig defined in file [C:\Users\...\build\classes\java\main\com\study\blogproject\config\WebOAuthSecurityConfig.class]
↑ ↓
| userService defined in file [C:\Users\...\build\classes\java\main\com\study\blogproject\service\UserService.class]
└─────┘
오류 메시지 중 "The dependencies of some of the beans in the application context form a cycle"는 의존성에 순환이 발생했다는 의미이다. Spring Boot에서는 기본적으로 순환 의존성을 허용하지 않는데, 오류 메시지에서 짚어준 파일을 보면, WebOAuthSecurityConfig.class와 UserSevice.class, 이 두 class에서 서로를 의존하는 것으로 보인다. 그래서 그 두 파일을 살펴보았다.
아래 코드를 보고 처음에는 WebOAuthSecurityConfig 클래스는 UserService를 주입받고 있으나, UserService는 WebOAuthSecurityConfig를 주입받지 않고 있다고 생각했다. 하지만 잘 보면, WebOAuthSecurityConfig에 @Bean으로 정의된 BcryptPasswordEncoder를 주입받고 있음을 알 수 있다. 이로 인해 순환 의존성 문제가 발생한 것이다.
/** UserService.java **/
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
// WebOAuthSecurityConfig에서 @Bean으로 정의된 BCryptPasswordEncoder 주입
public Long save(AddUserRequest dto) {
return userRepository.save(User.builder()
.email(dto.getEmail())
.password(bCryptPasswordEncoder.encode(dto.getPassword()))
.build()).getId();
}
/** 생략 **/
}
/** WebOAuthSecurityConfig.java **/
@RequiredArgsConstructor
@Configuration
public class WebOAuthSecurityConfig {
private final OAuth2UserCustomService oAuth2UserCustomService;
private final TokenProvider tokenProvider;
private final RefreshTokenRepository refreshTokenRepository;
private final UserService userService; //UserService 주입
/** 생략 **/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
따라서 이를 해결하기 위해 아래와 같이 코드를 수정해줬다. UserService 클래스 내에서 BcryptPasswordEncoder가 사용되는 메서드는 save 메서드밖에 없었기 때문에 메서드 안에서 BcryptPasswordEncoder를 생성해주었다. 이렇게 하면 UserService 클래스에서 더 이상 WebOAuthSecurityConfig 클래스에 의존하지 않기 때문에 WebOAuthSecurityConfig 클래스는 따로 수정하지 않아도 된다.
/** UserService.java 수정 **/
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
public Long save(AddUserRequest dto) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
return userRepository.save(User.builder()
.email(dto.getEmail())
.password(encoder.encode(dto.getPassword()))
.build()).getId();
}
}