JAVA/Spring Boot

[Validation] 누락된 값 전역 처리, 클라이언트에 상세히 표시

주코식딩 2023. 1. 25. 16:51

Validation의 메세지 처리는 생각보다 쉽지않다.

다음과 같이 작성된 Validation message는 서버에서만 확인 가능하다.

하지만 유효성 검사라는 것은 클라이언트에게 보여줘야 의미가 있지 서버에서 확인하는 것은 별로 의미가 없다.

@Getter
public class SpotStayListReqDto {

    @NotNull(message = "spotId가 비어 있습니다.")
    private Integer spotId;
    @NotEmpty(message = "checkInDate가 비어 있습니다.")
    @Size(min = 8, max = 8, message = "yyyyMMdd 형식으로 작성 바랍니다.")
    private String checkInDate;
    @NotEmpty(message = "checkOutDate가 비어 있습니다.")
    @Size(min = 8, max = 8, message = "yyyyMMdd 형식으로 작성 바랍니다.")
    private String checkOutDate;

    private Integer roomCnt;

    public SpotStayListReqDto(Integer spotId, String checkInDate, String checkOutDate, Integer roomCnt) {
        this.spotId = spotId;
        this.checkInDate = checkInDate;
        this.checkOutDate = checkOutDate;
        this.roomCnt = roomCnt;
    }
}

 

아무리 검색을 해 보아도 Controller 딴에서 BindResult 변수를 통해 직접 맵핑하는 방식밖에 나오지 않아 절망하던 중 ControllerAdvice에서 정답을 찾았다.

유효성 검사 실패시 Spring Boot는 BindException을 터트리는데 이 예외가 BindResult 정보를 가지고 있어서 Advice로 추가 작업을 해주었다.

사용할 정보를 debug 모드로 하나씩 뒤져서 쓰다보니 코드가 살짝 지져분 해졌지만 결과에 매우 만족한다.

@RestControllerAdvice
public class ExceptionAdvice extends RuntimeException {

    @ExceptionHandler(BindException.class)
    public ResponseEntity<CommonResDto<List<String>>> handleBindException(BindException e) {

        List<String> data = new ArrayList<>();

        for (ObjectError error : e.getBindingResult().getAllErrors()) {
            data.add(((DefaultMessageSourceResolvable) Objects.requireNonNull(error.getArguments())[0]).getDefaultMessage()
                    + " : " + error.getDefaultMessage());
        }

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(CommonResDto.<List<String>>builder()
                .code(ResponseCode.RESPONSE_0003.getCode()) 
                .message(ResponseCode.RESPONSE_0003.getDefaultMessage()) // 파라미터 유효성 검사 실패!
                .data(data)
                .build());
    }
}