DTO를 사용하고 @Valid로 DTO 데이터의 유효성까지 검사하는 과정까지 진행했다. 검증을 하기까진 했는데, 그럼 이제 들어온 데이터가 잘못된 형태라 검증을 실패한 경우는 어떻게 될까?
잘못 들어온 데이터에 대해 예외처리가 필요하다. 나는 일단 일정 관련된 기능들을 내가 담당하고 있으므로 이에 대한 DTO 예외처리를 할 예정이다.
일정의 Request가 잘못 들어왔음을 알리고자 ScheduleRequestException 객체를 만들었다.
...
public class ScheduleRequestException extends RuntimeException{
public Errors errors;
public ScheduleRequestException(Errors errors) {
this.errors = errors;
}
}
RuntimeException을 상속받고 검증이 잘못되어 에러 정보를 갖고 있는 Errors 객체를 저장해두도록 했다.
이제 ScheduleRequestExeption 객체가 던져졌을 때 후처리를 어떻게 할지 ExceptionHandler를 만들어보자.
나는 검증할 데이터들이 제대로 들어오지 않았음을 나타내기 위해 어느 요청이 잘못됐는지를 message로 뽑아서 보여주기로 했다.
@ExceptionHandler(ScheduleRequestException.class)
public ResponseEntity<BaseResponse<Object>> handler(ScheduleRequestException e){
ArrayList<String> messages = e.errors.getFieldErrors()
.stream()
.map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
.collect(Collectors.toCollection(ArrayList::new));
return ResponseEntity.badRequest()
.body(new BaseResponse<>(false, HttpStatus.BAD_REQUEST, "잘못된 입력입니다.", messages));
}
messages에는 각 필드 별 잘못 들어온 값들에 대해 디폴트로 설정해둔 오류 메세지를 출력하도록 리스트로 모아 body에 한꺼번에 출력시키도록 했다.
Controller 계층에서 검증하고자 하는 DTO는 createScheduleRequestDTO이다. 유효성 검증 실패 시 나갈 메세지를 message에 저장했다.
public record CreateScheduleRequestDTO(@NotBlank(message = "일정 제목은 필수 입력 값입니다.") String title,
@NotNull(message = "일정 국가는 필수 입력 값입니다.") Country country,
@NotNull(message = "일정 지역은 필수 입력 값입니다.") City city,
@NotNull(message = "시작 날짜는 필수 입력 값입니다.") LocalDate startDate,
@NotNull(message = "끝 날짜는 필수 입력 값입니다.") LocalDate endDate,
String memo
){
}
데이터 유효성을 검증하는 중에 발생한 에러 정보를 저장하는 인터페이스가 Errors 객체이다.
public ResponseEntity<BaseResponse<Object>> createSchedule(@AuthUser SecurityUser user, @RequestBody @Valid CreateScheduleRequestDTO createScheduleRequestDTO, Errors errors){
if (errors.hasErrors())
throw new ScheduleRequestException(errors);
...
}
이 메서드에서는 일정 생성 Request DTO에 대해 검증하고 잘못된 유효성 검증에 대한 에러 정보를 errors에 저장했다. 검증에 실패할 경우, errors.hasErrors()에 값이 들어가게 되고, ScheduleRequestException 객체에 해당 errors 정보를 넣어를 던지게 된다.
Postman으로 request body에 아무것도 없이 요청한 테스트 결과
제대로 검증하고 내 의도대로 에러 메세지를 출력해준다!