[Spring] Bean validation 응답 메시지 커스텀 하기 (ResponseEntityExceptionHandler)

Kim Dae Hyun·2022년 3월 12일
2
post-custom-banner

아래와 같이 Bean validation을 적용했을 때 에러 메시지를 확인해 볼께요.

public class ExpenseRequest {

    @NotBlank(message = "Expense name must not be empty.")
    private String name;
    @NotBlank(message = "Expense description must not be empty.")
    private String description;
    @NotNull(message = "Expense amount must not be null.")
    private Integer amount;
    @NotBlank(message = "Expense category must not be empty")
    private String category;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @NotNull(message = "Expense date must not be null")
    private LocalDate date;
    
    // ... 생략
}    

Bean validation을 적용했을 때 기본적으로 적용되는 메시지입니다.

@NotNull, @NotBlank 등으로 아주 쉽게 입력값에 대한 검증을 할 수 있었지만 에러 메시지의 포멧이 그리 친절하지는 않습니다.

message에 설정한 메시지만을 출력해주면 더 좋을 것 같습니다.


📌 ResponseEntityExceptionHandler

Bean validation에 의해 바인딩 된 에러를 꺼내서 에러 메시지를 커스텀 할 것 입니다.

@ControllerAdvice가 지정된 API에서 발생하는 예외를 처리하는 클래스에서 ResponseEntityExceptionHandler를 상속받아 사용합니다.

ResponseEntityExceptionHandler 의 여러 메서드 중 handleMethodArgumentNotValid를 재정의합니다.

그리고 Map으로 직접 HTTP 응답의 body를 만들어주면 됩니다.

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        Map<String, Object> body = new HashMap<>();

        body.put("statusCode", HttpStatus.BAD_REQUEST);
        body.put("timestamp", LocalDateTime.now());

        List<String> errors = ex.getBindingResult().getFieldErrors()
                .stream()
                .map(e -> e.getDefaultMessage())
                .collect(Collectors.toList());
        body.put("messages", errors);

        return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
    }
}

MethodArgumentNotValidExceptiongetBindingResult()getFieldErrors() 메서드로 현재 필드에 바인딩 된 모든 에러에 접근할 수 있습니다.

모든 필드에러의 메시지를 리스트로 만들어서 body로 구성하면 아래과 같은 결과를 만들 수 있습니다.

이전보다 확실히 깔끔한 에러 메시지를 구성할 수 있게 되었습니다 :) good

profile
좀 더 천천히 까먹기 위해 기록합니다. 🧐
post-custom-banner

0개의 댓글