@ControllerAdvice과 Swagger 사이에 일어난 충돌을 해결한 일기
서론 : Swagger 설정 후 오류 발생
Spring Boot에서 Swagger API (OpenAPI)**를 사용해 API 문서를 자동 생성하고 테스트하려고 했는데, @ControllerAdvice 와 충돌이 발생했다.
오류를 해결하기 위해 몇 시간 동안 삽질한 상황을 회고하며 글을 쓴다..
발생 전 : Swagger 설정
- Swagger 관련 의존성 추가
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
- 이 의존성을 추가하면 /swagger-ui/index.html에서 API 문서를 확인할 수 있다.
- Swagger Configuration 설정
@Configuration
public class OpenApiConfiguration {
private static final String API_VERSION = "v1";
private static final String API_NAME = "Discodeit API 문서";
private static final String API_DESCRIPTION = "Discodeit 프로젝트의 Swagger API 문서입니다";
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title(API_NAME)
.version(API_VERSION)
.description(API_DESCRIPTION));
}
이 설정을 추가하고 실행하면 /swagger-ui/index.html에서 API 문서를 확인할 수 있어야 한다.
그런데…**오류 발생!**😱
오류 발생 : Failed to load API definition
Swagger UI에 접속했더니 다음과 같은 오류가 발생했다.
로그를 확인해보니, NoSuchMethodError: 'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)' 라는 오류가 발생했다.
=> ControllerAdviceBean 클래스의 생성자 중 ControllerAdviceBean.<init>(java.lang.Object)를 찾을 수 없다는 의미
확실히 ControllerAdvice와의 호환 문제이다.
1. ControllerAdvice O, Swagger X 인 경우 => 잘 돌아감
2. ControllerAdvice X, Swagger O 인 경우 => 잘 돌아감
2. ControllerAdvice O, Swagger O 인 경우 => 오류 발생
충돌이 일어나는 중인 것 같다.
삽질 과정 (해결 시도)
@RestControllerAdvice(basePackages = {"com.sprint.mission.controller"})
public class CustomErrorAdvice {
- 이거의 속성을 계속 건드렸었다
**1. 애노테이션 속성 건들도**
@RestControllerAdvice(annotations = RestController.class, basePackages = {"com.sprint.mission.controller"})
public class CustomErrorAdvice {
// 애노테이션 설정
**2. 대상 컨트롤러도 따로 설정해봐도**
@RestControllerAdvice(annotations = RestController.class, basePackageClasses = {AuthController.class, BinaryContentController.class, ChannelController.class, ReadStatusController.class})
public class CustomErrorAdvice {
**3. 이런 방법을 진행해도....**
private static final List<String> SWAGGER_WHITELIST = List.of(
"/v3/api-docs", "/swagger-ui", "/swagger-ui.html", "/swagger-resources"
);
....
@ExceptionHandler(Exception.class)
public ResponseEntity<CustomErrorResponse> handleException(Exception e) {
// Swagger 관련 요청이면 예외 핸들링 하지 않고 그대로 진행
if (SWAGGER_WHITELIST.stream().anyMatch(requestURI::contains)) {
throw new RuntimeException(ex);
}
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(
CustomErrorResponse.builder()
.status(HttpStatus.INTERNAL_SERVER_ERROR.value()+"")
.message(e.getMessage())
.build()
);
- annotations 속성 추가 ⇒ 실패
- 컨트롤러 클래스 직접 지정 ⇒ 실패
- Swagger 관련 요청을 예외 처리에서 제외 ⇒ 실패
전혀 해결되지 않았다
해결 방법: Spring Boot 버전 다운그레이드
이런저런 시도를 다 해도 안 되길래, 결국 Spring Boot 버전을 낮춰보았다.
기존 버전 | 변경된 버전 |
3.4.2 | 3.3.9 |
버전이 문제였다
이거 해결하려고 몇시간을 삽질한건지 ㅠㅠ
결국 @ControllerAdvice와 springdoc-openapi의 최신 버전 간의 호환성 문제였다. 개발할 때 가장 시간 많이 잡아먹는 게 코딩이 아니라 오류 찾기라는 걸 다시 한번 깨달았다.
이제 Swagger API 문서도 정상적으로 동작하니, 본격적인 개발을 이어나가겠다
“버전 downGrading 잊지 말기!”
'백엔드 > 스프링' 카테고리의 다른 글
단위 테스트가 어려운 이유: 과도한 Mocking (0) | 2025.03.29 |
---|---|
복잡한 동적 쿼리 테스트하기 (0) | 2025.03.27 |
Spring에서 파일 다운로드 코드 구현하기 (다양한 리소스) (0) | 2025.03.10 |
Swagger 테스트 시 - application/octet-stream is not supported (0) | 2025.03.05 |
외부 API 호출하는 방법 (feat. RestClient) (0) | 2025.02.20 |