Spring Boot ConflictingBeanDefinitionException 해결하기
Spring Boot ConflictingBeanDefinitionException 해결하기
Spring Boot 프로젝트 개발 중 ConflictingBeanDefinitionException이 발생했다. 콘서트 예약 시스템을 구현하면서 마주친 이 문제와 해결 과정을 기록한다.
문제 상황
테스트 실행 시 다음과 같은 오류가 발생했다:
1
2
3
org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'paymentGateway' for bean class [...PaymentGatewayImpl]
conflicts with existing, non-compatible bean definition of same name
원인 분석
문제의 원인은 두 가지였다:
- 구현체 누락:
PaymentGateway인터페이스는 정의했지만 실제 구현체가 없었다 - ComponentScan 필터: 과도한 필터링으로 인해 필요한 Bean도 제외되고 있었다
1
2
3
4
5
6
7
// 문제가 된 ComponentScan 설정
@ComponentScan(
basePackages = "kr.hhplus.be.server",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test.*") // 너무 광범위
}
)
해결 방법
1단계: PaymentGateway 구현체 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component
public class PaymentGatewayImpl implements PaymentGateway {
@Override
public Payment processPayment(Payment payment) {
try {
// 결제 처리 시뮬레이션
Thread.sleep(100);
return payment.complete("txn-" + System.currentTimeMillis());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("결제 처리 중 오류가 발생했습니다.", e);
}
}
}
2단계: 테스트용 구현체 분리
1
2
3
4
5
6
7
8
9
10
@Component
@Profile("test")
public class MockPaymentGatewayImpl implements PaymentGateway {
@Override
public Payment processPayment(Payment payment) {
// 테스트용 즉시 완료 처리
return payment.complete("test-txn-" + System.currentTimeMillis());
}
}
3단계: ComponentScan 필터 개선
1
2
3
4
5
6
7
8
9
10
11
12
@SpringBootApplication
@ComponentScan(
basePackages = "kr.hhplus.be.server",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test[s]?$") // 더 정확한 패턴
}
)
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
대안적 해결책
ComponentScan을 완전히 제거하고 Spring Boot의 기본 패키지 스캔을 사용하는 것도 가능하다:
1
2
3
4
5
6
@SpringBootApplication // ComponentScan 제거
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
}
교훈
인터페이스를 정의할 때는 반드시 구현체도 함께 제공해야 한다. ComponentScan 필터를 사용할 때는 예상치 못한 Bean 제외가 발생할 수 있으므로 신중하게 패턴을 작성해야 한다.
This post is licensed under CC BY 4.0 by the author.