본문 바로가기
Programming/Spring

@RestControllerAdvice로 ExceptionHandling 하기

by peter paak 2020. 7. 15.
728x90

ErrorCode

api에서 사용하는 모든 에러코드를 모아 놓은 곳입니다.

@Getter
@RequiredArgsConstructor
public enum ErrorCode {

    SERVER_ERROR(500, "서버 에러", 5000);

    private final int status;
    private final String message;
    private final int code;
}

status

  • HttpStatus의 value 값

message

  • 클라이언트에 보내줄 에러 메세지

code

  • 해당 ErrorCode가 가지는 고유한 에러 매핑코드

ApiException

RuntimeException을 상속받는 구현체. 실제로 에러를 발생시키는 Exception 객체이다. IllegalArgumentException이나 NullPointException처럼 throw new ApiException() 형식으로 에러를 발생하도록 사용된다. 내부적으로는 방금 정의한 에러의 내용이 담긴 ErrorCode를 가지고 있다.

@Getter
public class ApiException extends RuntimeException {

    private ErrorCode errorCode;

    public ApiException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }

    public int getStatus() {
        return errorCode.getStatus();
    }
}

ErrorResponse

Response 객체에서 data필드에 들어갈 객체이다. 생김새는 ErrorCode와 흡사하지만 Responsedata필드 타입은 Generic으로 만약 ErrorCode를 enum 객체를 넣게되면 String 형식으로 출력이 된다. 그래서 ErrorCode를 객체 형식으로 전달하는 Dto 개념으로 사용된다.

@Getter
public class ErrorResponse {

    private String message;
    private int code;
    private int status;

    @Builder
    public ErrorResponse(String message, int code, int status) {
        this.message = message;
        this.code = code;
        this.status = status;
    }

    public static ErrorResponse of(ErrorCode errorCode) {
        return ErrorResponse.builder()
                .message(errorCode.getMessage())
                .code(errorCode.getCode())
                .status(errorCode.getStatus())
                .build();
    }
}

ApiExceptionController

에러가 발생한 내용을 Controller하는 클래스이다. 서버 어디에선가 throw new ApiException()을 호출한다면 @RestControllerAdvice@Exceptionhandler에게 전달을 한다. 앞서 정의한 Response 객체에 ApiExceptionErrorCode의 내용을 전달해줌으로써 Response에 해당 내용들을 보여줄 수 있게된다.

@RestControllerAdvice
public class ApiExceptionController {

    @ExceptionHandler(RuntimeException.class)
    protected Response<ErrorResponse> handleRuntimeException(ApiException apiException) {
        return Response.of(
                apiException.getStatus(),
                ErrorResponse.of(apiException.getErrorCode()));
    }
}

사용해보기

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        throw new ApiException(ErrorCode.SERVER_ERROR);
    }
}

728x90