본문 바로가기
Spring

[Springboot] @RestControllerAdvice 와 Swagger 충돌 문제

by worldcenter 2025. 8. 27.

 

🚨 에러 발생 원인

커스텀 예외 클래스를 만들기 위해 도메인 레벨 표현을 위한 enum 클래스, 커스텀 예외 클래스, 커스텀 예외를 처리하는 ExceptionHandler 클래스를 생성하였습니다.

// 도메인 레벨 표현을 위한 열거형 클래스 생성

public class Constants {

    public enum ExceptionClass {

        PRODUCT("Product");
        ORDER("Order");

        private String exceptionClass;

        ExceptionClass(String exceptionClass) {
            this.exceptionClass = exceptionClass;
        }

        public String getExceptionClass() {
            return exceptionClass;
        }


        @Override
        public String toString() {
            return getExceptionClass() + " Exception. ";
        }
    }
}
// 커스텀 예외 클래스

public class CustomException extends Exception {

    private Constants.ExceptionClass exceptionClass;
    private HttpStatus httpStatus;

    public CustomException(Constants.ExceptionClass exceptionClass, HttpStatus httpStatus, String message) {
        super(exceptionClass.toString() + message);
        this.exceptionClass = exceptionClass;
        this.httpStatus = httpStatus;
    }

    public Constants.ExceptionClass getExceptionClass() {
        return exceptionClass;
    }

    public int getHttpStatusCode() {
        return httpStatus.value();
    }

    public String getHttpStatusType() {
        return httpStatus.getReasonPhrase();
    }

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }
}
// ExceptionHandler 클래스

@RestControllerAdvice
public class CustomExceptionHandler {

    @ExceptionHandler(value = CustomException.class)
    public ResponseEntity<Map<String, String>> handleException(
            CustomException e, HttpServletRequest request) {

        HttpHeaders responseHeaders = new HttpHeaders();
        HttpStatus httpStatus = HttpStatus.BAD_REQUEST;

        Map<String, String> map = new HashMap<>();
        map.put("error type", e.getHttpStatusType());
        map.put("code", Integer.toString(e.getHttpStatusCode()));
        map.put("message", e.getMessage());

        return new ResponseEntity<>(map, responseHeaders, e.getHttpStatus());

    }
}

 

모든 클래스 작성 완료 후 애플리케이션을 실행하니 아래와 같은 에러가 발생했습니다.

java.lang.NoSuchMethodError: 'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)

 

또한 Swagger도 500에러가 발생하며 접속이 안되는 것을 볼 수 있었습니다.

 

 

‼️ 해결 방안

커스텀 예외 생성 전까지는 정상적으로 애플리케이션이 동작하던 것을 기억하고 @RestControllerAdvice 어노테이션을 삭제하고 애플리케이션을 재실행 했습니다. 결과를 확인해보니 정상적으로 Swagger 및 애플리케이션이 동작하는 것으로 보아 @RestControllerAdvice에서 발생하는 문제라는 것을 확인할 수 있습니다.

 

 

Spring OpenAPI 3 공식문서를 확인해보니 @ControllerAdvice를 사용하는 경우 문서를 생성하는 Swagger와 충돌이 발생할 수 있다는 것을 알게 됐습니다. 

@ControllerAdvice를 사용하지 않으면 Swagger는 컨트롤러 클래스들을 반영하여 API 정의를 분석하고 정상적으로 동작합니다. 하지만, @ControllerAdvice를 사용하게 되면, Swagger의 응답 또한 ControllerAdvice에 의해 변환되므로 Swagger 웹 페이지가 응답 구조를 인식하지 못하게 됩니다. 

이를 해결하기 위해 프로젝트 패키지에서 @ControllerAdvice가 적용될 곳을 명시하면 Swagger 응답이 변환되지 않아 충돌을 해결할 수 있다는 StackOverFlow 정보를 확인하여 아래와 같이 코드 수정 후 애플리케이션을 재실행 했습니다.

@RestControllerAdvice(basePackages = {"com.springboot.spring_jpa.controller.ExceptionController"})
public class CustomExceptionHandler {

    ...
}

 

하지만 여전히 동일한 문제가 발생하였고 최신 Swagger ui 버전을 업그레이드 한다면 해당 충돌을 피할 수 있는지 확인하기 위해 gradle에서 Swagger ui 버전을 2.6.0(기존) -> 2.8.11(변경) 으로 업그레이드 하였습니다.

dependencies {
	// swagger (기존 2.6.0)
	implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.11'
	...
}

 

그 결과 아래와 같이 정상적으로 Swagger가 실행되고@RestControllerAdvice 또한 작동되는 것을 볼 수 있었습니다.

Spring OpenAPI 공식 문서에 따르면 Springboot 3.x 버전의 경우 Springdoc-openapi 2.x 버전을 사용해야 합니다.

 

 

참고 링크

https://dev-meung.tistory.com/entry/%ED%95%B4%EC%BB%A4%ED%86%A4-HY-THON-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85-Swagger-500-%EC%97%90%EB%9F%AC-Failed-to-load-API-definition

 

[트러블슈팅] Swagger 500 에러: Failed to load API definition

🐛이슈- 발생한 오류 copy & paste- 오류가 발생한 상황 간략히 설명각자 API를 구현하던 중 팀원분이 [응답 통일 및 에러 핸들러]를 구현해서 PR을 올려주셨다. API 역할 분배할 때 되도록이면 엔티티

dev-meung.tistory.com

https://stackoverflow.com/questions/64473435/controlleradvice-does-not-allow-swagger-ui-to-be-displayed

 

@ControllerAdvice does not allow Swagger UI to be displayed

I just add a GlobalExceptionHandler with @ControllerAdvice and when i try to access Swagger UI at http://localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/ a get a message...

stackoverflow.com

https://github.com/springdoc/springdoc-openapi?tab=readme-ov-file

 

GitHub - springdoc/springdoc-openapi: Library for OpenAPI 3 with spring-boot

Library for OpenAPI 3 with spring-boot. Contribute to springdoc/springdoc-openapi development by creating an account on GitHub.

github.com