• 자바 예외처리 @ControllerAdvice 사용해보기

    2023. 3. 7.

    by. Sohyun

    • 에러를 우아하게 잡는 것과 일정하게 응답하는 것이 목표였다.
    • 개개별 에러를 잡을 수 있는 ExceptionHandler와 전반적인 에러를 잡아주는 RestControllerAdvice를 조합하였다.
    • 쉽게 가자면 RuntimeException을 상속받은 커스터마이징 한 에러들의 클래스들을 줄줄이 생성하는 방법도 있겠지만 지저분해질 것 같아서 피하고 싶었다.

    • GlobalControllerAdvice.java

    : 컨트롤러에서 발생하는 에러를 받는다.

    @Slf4j
    @ControllerAdvice
    public class GlobalControllerAdvice {
    
        @ResponseBody
        @ExceptionHandler(CustomException.class)
        public ResponseEntity<ErrorResponse> CustomException(CustomException e) {
            return ErrorResponse.responseEntity(e.getErrorCode());
        }
    }
    • ErrorResponse.java

    : 에러 응답용 템플릿

    @Getter
    @RequiredArgsConstructor
    @Builder
    public class ErrorResponse {
    
        private final LocalDateTime timestamp = LocalDateTime.now();
        private final int status;
        private final String error;
        private final String code;
        private final String message;
    
        public static ResponseEntity<ErrorResponse> responseEntity(ErrorCode errorCode) {
            return ResponseEntity
                    .status(errorCode.getHttpStatus())
                    .body(ErrorResponse.builder()
                            .status(errorCode.getHttpStatus().value())
                            .error(errorCode.getHttpStatus().name())
                            .code(errorCode.name())
                            .message(errorCode.getMessage())
                            .build());
    
        }
    
    }
    
    • CustomException.java

    : 중간다리를 하도록 만들었다.

    RuntimeException 대신 받을 수 있고,

    ErrorCode를 내제하고 있어서 발생한 곳에서 응답으로 실어날라 준다.

    import lombok.Getter;
    import lombok.RequiredArgsConstructor;
    
    @Getter
    @RequiredArgsConstructor
    public class CustomException extends RuntimeException {
    
        private final ErrorCode errorCode;
    }
    
    • ErrorCode.enum

    : 반복코드를 줄이고 상수화하기 위한 Enum 클래스로 만들었다.

    에러내용(상태코드, 에러메시지)

    @Getter
    @RequiredArgsConstructor
    public enum ErrorCode {
    
        UNAUTHORIZED_MEMBER(HttpStatus.BAD_REQUEST, "아이디 비밀번호가 올바르지 않거나 회원이 아닙니다.");
    
        private final HttpStatus httpStatus;
        private final String message;
    
    }
    

    이렇게 사용하면

    기존 : throw new RuntimeException("아이디 비밀번호가 올바르지 않거나 회원이 아닙니다.");

    throw new CustomException(ErrorCode.UNAUTHORIZED_MEMBER);
    

    이렇게 응답한다.

    참고페이지 (작성하신 분 감사합니다 😊)

    Spring Exception Handling

    우아할지는 모르겠으나 목표에는 부합하는 것 같아서 뿌듯하다!

    개요

    • 에러를 우아하게 잡는 것과 일정하게 응답하는 것이 목표였다.
    • 개개별 에러를 잡을 수 있는 ExceptionHandler와 전반적인 에러를 잡아주는 RestControllerAdvice를 조합하였다.
    • 쉽게 가자면 RuntimeException을 상속받은 커스터마이징 한 에러들의 클래스들을 줄줄이 생성하는 방법도 있겠지만 지저분해질 것 같아서 피하고 싶었다.
    • GlobalControllerAdvice.java

    : 컨트롤러에서 발생하는 에러를 받는다.

    @Slf4j
    @RestControllerAdvice
    public class GlobalControllerAdvice {
    
        @ResponseBody
        @ExceptionHandler(CustomException.class)
        public ResponseEntity<ErrorResponse> CustomException(CustomException e) {
            return ErrorResponse.responseEntity(e.getErrorCode());
        }
    }
    
    • ErrorResponse.java

    : 에러 응답용 템플릿

    @Getter
    @RequiredArgsConstructor
    @Builder
    public class ErrorResponse {
    
        private final LocalDateTime timestamp = LocalDateTime.now();
        private final int status;
        private final String error;
        private final String code;
        private final String message;
    
        public static ResponseEntity<ErrorResponse> responseEntity(ErrorCode errorCode) {
            return ResponseEntity
                    .status(errorCode.getHttpStatus())
                    .body(ErrorResponse.builder()
                            .status(errorCode.getHttpStatus().value())
                            .error(errorCode.getHttpStatus().name())
                            .code(errorCode.name())
                            .message(errorCode.getMessage())
                            .build());
    
        }
    
    }
    
    • CustomException.java

    : 중간다리를 하도록 만들었다.

    RuntimeException 대신 받을 수 있고,

    ErrorCode를 내제하고 있어서 발생한 곳에서 응답으로 실어날라 준다.

    import lombok.Getter;
    import lombok.RequiredArgsConstructor;
    
    @Getter
    @RequiredArgsConstructor
    public class CustomException extends RuntimeException {
    
        private final ErrorCode errorCode;
    }
    
    • ErrorCode.enum

    : 반복코드를 줄이고 상수화하기 위한 Enum 클래스로 만들었다.

    에러내용(상태코드, 에러메시지)

    @Getter
    @RequiredArgsConstructor
    public enum ErrorCode {
    
        UNAUTHORIZED_MEMBER(HttpStatus.BAD_REQUEST, "아이디 비밀번호가 올바르지 않거나 회원이 아닙니다.");
    
        private final HttpStatus httpStatus;
        private final String message;
    
    }
    

    이렇게 사용하면

    기존 : throw new RuntimeException("아이디 비밀번호가 올바르지 않거나 회원이 아닙니다.");

    throw new CustomException(ErrorCode.UNAUTHORIZED_MEMBER);
    

    이렇게 응답한다.

     

    참고페이지 (작성하신 분 감사합니다 😊)

    Spring Exception Handling

     

    Spring Exception Handling

    1. Java Exception Java 에는 Checked Exception 과 Unchecked Exception 이 존재합니다. 이 둘은 헷갈리기 쉽지만 사실 큰 차이가 존재합니다. Checked Unchecked 예외 처리 필수 필수 아님 트랜잭션 롤백 안됨 기본값

    bcp0109.tistory.com

    우아할지는 모르겠으나 목표에는 부합하는 것 같아서 뿌듯하다!

    댓글