기본적으로 스프링은 요청에 대해서 예외가 발생하면 Whitelabel Error Page가 보여진다
하지만 일반 사용자한테 저런 에러 페이지를 보여주는 것보다 의미 있는(?), 알 수 있는 문구를 보여주면 좋을 것이다.
스프링에서는 @RestControllerAdvic를 사용해서 예외를 깔끔하게 처리할 수 있다.
예외가 발생하면 미리 정의해놓은 응답으로 보낼 수 있다.
간단하게 예제를 만들어 보겠다.
ErrorCode
@RequiredArgsConstructor
@Getter
public enum ErrorCode {
NOT_FOUND_USER(HttpStatus.NOT_FOUND, "회원을 찾을 수 없습니다."),
NEED_TO_LOGIN(HttpStatus.UNAUTHORIZED, "로그인이 필요합니다.");
private final HttpStatus httpStatus;
private final String description;
}
에러 코드를 보관하는 enum 클래스이다. Http 상태와 설명을 가지고 있다. 필요에 따라 이 클래스에서 에러 코드를 추가하면 된다. Enum 클래스를 사용하기 전에는 하나하나 예외 클래스를 만들었었는데 관리하기가 까다로웠는데 Enum은 깔끔하다.
CustomException
@Getter
public class CustomException extends RuntimeException {
private final ErrorCode errorCode;
public CustomException(ErrorCode errorCode) {
this.errorCode = errorCode;
}
public CustomException(ErrorCode errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
}
RuntimeExcepion을 상속하는 CustomException을 만들었다. RuntimeException에 간략히 설명하자면 Unchecked Exception으로 예외 처리를 강제하지 않는다. 서버 특성상 상태를 유지하지 않기 때문에 잘못된 요청이 들어오면 바로잡기보단 예외를 던지고 끝내는게 깔끔하다.
ErrorResponse
@Getter
@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;
private final String description;
public static ResponseEntity<ErrorResponse> toResponseEntity(CustomException e) {
ErrorCode errorCode = e.getErrorCode();
return ResponseEntity
.status(errorCode.getHttpStatus())
.body(ErrorResponse.builder()
.status(errorCode.getHttpStatus().value())
.error(errorCode.getHttpStatus().name())
.code(errorCode.name())
.message(errorCode.getDetail())
.description(e.getMessage())
.build()
);
}
}
예외 발생 시 반환하는 응답 객체이다.
(여기서 좀 삽질을 했는데 @Getter가 없으면 제대로 작동이 안 한다. 내부적으로 get 프로퍼티가 필요한가 보다)
GlobalExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {CustomException.class})
protected ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
return ErrorResponse.toResponseEntity(e);
}
}
@RestControllerAdvice을 클래스명 위에 추가해준다.
@ExceptionHandler의 value에 처리하고 싶은 예외 클래스를 기입하면 된다.
CustomException.class 예외가 발생하면 handleCustomException 메소드가 실행이 되어 응답 객체를 반환한다.
AdviseController
@RestController
@RequestMapping("/advise")
public class AdviseController {
@GetMapping
public String throwException() {
throw new CustomException(ErrorCode.NEED_TO_LOGIN);
}
}
참고 : Spring Exception Handling :: 뱀귤 블로그 (tistory.com)
'Spring' 카테고리의 다른 글
Spring의 @Transactional (0) | 2021.12.15 |
---|---|
JDK Dynamic Proxy와 CGLIB (0) | 2021.12.07 |
Spring AOP (0) | 2021.12.02 |
Spring Boot에 Redis Cache 적용해보기 (0) | 2021.11.25 |
Spring JPA Specification을 사용해 유연하게 조회 API 만들기 (3) | 2021.11.08 |
댓글