@RestControllerAdvice 예외 처리방법

Yeeun_Kim·2024년 7월 15일
0
post-thumbnail

1. @ControllerAdvice & @RestControllerAdvice

  • ControllerAdvice는 여러 Controller에 대해 전역적으로 ExceptionHandler를 적용해 준다. ControllerAdvice가 선언된 클래스는 Spring Bean으로 등록되기 때문에 전역적으로 에러를 핸들링 하는 클래스를 만들어 어노테이션을 붙어줌으로써 에러 처리를 위임할 수 있다.
  • RestControllerAdvicce는 ControllerAdivce와 달리 @ResponseBody가 붙어 있어 응답을 Json으로 내려준다는 점에서 다르다.

ControllerAdvice 사용 이유

1) 하나의 클래스로 모든 컨트롤러에 대해 전역적으로 예외 처리 가능
2) 직접 정의한 에러 응답을 일관성있게 클라이언트에게 내려줄 수 있음
3) 별도의 try-catch문이 없어 코드의 가독성이 높아짐

ControllerAdvice 사용시 주의사항

  • 한 프로젝트당 하나의 ControllerAdvice만 관리하는 것이 좋음
  • 만약 여러 ControllerAdvice가 필요하다면 basePackages나 annotations 등을 지정해야 함.
  • 직접 구현한 Exception 클래스들은 한 공간에서 관리

2. @RestControllerAdvice를 이용한 Spring 예외 처리

에러 코드 정의하기
/*
	공통 ErrorCode Interface
*/
public interface ErrorCode {
    String name();
    HttpStatus getHttpStatus();
    String getMessage();
}
/*
	ErrorCode 구현체로 공통 Error Enum
*/
@Getter
@RequiredArgsConstructor
public enum CommonErrorCode implements ErrorCode{
    INVALID_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
    SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버오류 입니다."),
    NOT_FOUND_ERROR(HttpStatus.NOT_FOUND, "찾을 수 없는 항목입니다.")
    ;
    private final HttpStatus httpStatus;
    private final String message;
}
/*
	Custom Exception
*/
@Getter
@RequiredArgsConstructor
public class RestApiException extends RuntimeException{
    private final ErrorCode errorCode;
}
/*
	공통 Error 응답 형태
*/
@Getter
@Builder
public class ErrorResponse {
    private String name;
    private String message;
}
@RestControllerAdvice 구현
/*
	전역 예외 처리
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(RestApiException.class)
    public ResponseEntity<ErrorResponse> handleCustomException(RestApiException e) {
        ErrorCode errorCode = e.getErrorCode();
        return ResponseEntity.status(errorCode.getHttpStatus())
                .body(makeErrorResponse(errorCode));
    }

    @ExceptionHandler({Exception.class})
    public ResponseEntity<ErrorResponse> handleAllExcpetion(Exception ex) {
        log.warn("handleAllException", ex);
        ErrorCode errorCode =CommonErrorCode.SERVER_ERROR;
        return ResponseEntity.status(errorCode.getHttpStatus())
                .body(makeErrorResponse(errorCode));
    }

    public ErrorResponse makeErrorResponse(ErrorCode e) {
        return ErrorResponse.builder()
                .name(e.name())
                .message(e.getMessage())
                .build();
    }
}

회고

참고 자료를 바탕으로 작성한 글로써 전역 예외처리 방법에 대해 배우게 되었다. 무분별한 예외 처리가 아닌 공통적으로 예외를 작성할 수 있다는 점과 예외에 대한 응답이 일관성을 가질 수 있다는 점에서 팀 내부에서 예외에 대한 기준점과 명확한 내용을 바탕으로 사용한다면 유용하게 처리가 가능할 것 같다.

참고
https://mangkyu.tistory.com/205

0개의 댓글