인프런 커뮤니티 질문&답변

백엔드 주니어 개발자님의 프로필 이미지
백엔드 주니어 개발자

작성한 질문수

Spring boot에서 일반 예외처리와 api예외처리 한번에 하는 좋은 방법 없을까요?

작성

·

308

0

@Slf4j
@ControllerAdvice
@RequiredArgsConstructor
public class ExceptionControllerAdvisor {

    private final HttpServletRequest httpServletRequest;
    private final HttpServletResponse httpServletResponse;

    @ExceptionHandler(RollbackTriggeredException.class)
    public ResponseEntity<ErrorResponse> rollBackException(RollbackTriggeredException e) throws IOException {
        if (httpServletRequest.getRequestURI().startsWith("/api")) {
            int statusCode = e.getStatusCode();

            ErrorResponse body = ErrorResponse.builder()
                    .code(String.valueOf(statusCode))
                    .message(e.getMessage())
                    .validation(e.getValidation())
                    .build();

            return ResponseEntity.status(statusCode)
                    .body(body);
        } else {
            httpServletResponse.sendError(e.getStatusCode());
            return null;
        }
    }
}

spring boot와 thymeleaf를 사용해서 이런식으로 api 요청일 경우 해당 요청 uri의 앞에 api를 넣어서 api가 앞에있으면 ResponseEntity객체를 이용해서 RuntimeException을 상속받은 커스텀 예외(RollbackTriggeredException)을 처리하고, api 가 없다면 HttpServletResponse객체의 sendError 메서드를 사용해서 에러를 발생시킨다음 Spring boot의 예외처리 매커니즘을 통해 에러페이지로 이동하도록 코드를 짜보았습니다.

 

하지만 else부분에 else를 작성해줘야한다는 점이 좀 좋지 않은 코드는 아닐까 하는 생각이들게 되더라고요??

일반예외(페이지 이동하다 예외가 발생했을경우)와 api예외(ajax요청하다 예외가 발생했을 때)를 동시에 처리하는 좋은 방법있으면 알려주신다면 감사하겠습니다.

답변 1

0

안녕하세요, 백엔드 개발자 취준생님! 일반 예외처리와 API 예외처리를 한 번에 처리하는 좋은 방법에 대해 알려드릴게요.

Spring Boot에서는 @RestControllerAdvice 어노테이션을 사용하여 일반 컨트롤러와 API 컨트롤러에서 발생한 예외를 모두 처리할 수 있습니다. 이렇게 하면 별도의 분기처리 없이 한 곳에서 모든 예외를 처리할 수 있는 장점이 있어요.

아래는 예시 코드입니다:

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class ExceptionControllerAdvisor {

    @ExceptionHandler(RollbackTriggeredException.class)
    public ResponseEntity<ErrorResponse> handleRollBackException(HttpServletRequest request, RollbackTriggeredException e) {
        if (isAjax(request)) {
            int statusCode = e.getStatusCode();

            ErrorResponse body = ErrorResponse.builder()
                    .code(String.valueOf(statusCode))
                    .message(e.getMessage())
                    .validation(e.getValidation())
                    .build();

            return ResponseEntity.status(statusCode)
                    .body(body);
        } else {
            throw e;
        }
    }

    private boolean isAjax(HttpServletRequest request) {
        String accept = request.getHeader("accept");
        return accept != null && accept.contains("application/json");
    }
}

@RestControllerAdvice 어노테이션을 사용하여 예외 처리를 위한 공통 Controller Advice를 정의합니다. 그리고 @ExceptionHandler 어노테이션을 사용하여 특정 예외를 처리하는 메소드를 작성합니다.

isAjax() 메소드를 사용하여 현재 요청이 Ajax 요청인지를 확인합니다. 요청이 Ajax 요청일 경우는 API 예외처리를, 일반적인 브라우저 요청일 경우는 예외를 다시 던져서 Spring Boot의 예외 처리 매커니즘에게 처리를 맡기도록 합니다.

이렇게 하면 if-else 구문을 사용하지 않고도 일반 예외와 API 예외를 한 번에 처리할 수 있습니다. 이 방법을 활용하시면 코드의 가독성과 유지보수성을 향상시킬 수 있을 거예요. 감사합니다!

정말 감사합니다!ㅎㅎ

백엔드 주니어 개발자님의 프로필 이미지
백엔드 주니어 개발자

작성한 질문수

질문하기