
이번에는 잘못된 데이터 요청이 왔을 경우 검증을 하는 법을 알아보겠습니다.
예를들어, 이름이 없고 현재 2024년이지만 생일이 2030년인 사람의 데이터를 생성하려고 할 때 생성이 되면 안되겠죠?? 이런 경우를 대비해서 정확한 데이터의 요청이 들어오는지 검증하는 법을 배우겠습니다.
먼저 포스트맨을 사용해서 데이터 요청을 해보겠습니다.


이름이 빈칸이고, 생일이 먼 미래이지만 201을 반환하면서 정상적으로 생성이됩니다. 이러면 안됩니다. 수정해 보겠습니다.
먼저, 유효성 검증을 위해서 의존성이 필요합니다.
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = service.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("{id}")
.buildAndExpand(savedUser.getId())
.toUri();
return ResponseEntity.created(location).build();
}
@Valid : 주로 Spring Framework 등의 프레임워크에서 폼 입력값이나 API 요청의 데이터를 검증할 때 활용됩니다.

검증이 잘 되어서 400이 반환됩니다. 사용자의 어떤 문제 때문에 400번이 응답된지는 알수가 없습니다. REST API는 사용자가 사용하기 편하게 만드는 것이 가장 중요합니다.
더 자세한 내용을 출력하기 위해 CustomizedResponseEntityExceptionHandler를 사용해서 메서드를 정의하겠습니다.
MethodArgumentNotValidException을 발생시킵니다.MethodArgumentNotValidException을 처리할 수 있는 메서드를 오버라이딩해서 BAD_REQUEST(400) 응답을 보내겠습니다.@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(),
request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

앞에서 만든 ErrorDetails 클래스를 사용해서 예쁘게 예외를 처리하는 모습입니다.
하지만 message를 보면 너무 많은 정보를 보여주고 있습니다.
User에 가서 Valid message를 변경해 보겠습니다.
package study.rest.webservices.restfulwebservices.user;
import jakarta.validation.constraints.Past;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
public class User {
private Integer id;
@Size(min = 2, message = "이름은 최소 2글자 이상이어야 합니다.")
private String name;
@Past(message = "생일의 날짜는 과거여야 합니다.")
private LocalDate birthDate;
public User(Integer id, String name, LocalDate birthDate) {
this.id = id;
this.name = name;
this.birthDate = birthDate;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", birthDate=" + birthDate +
'}';
}
}
handleMethodArgumentNotValid() 수정//수정 전
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getMessage(),
request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
//수정 후
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(LocalDateTime.now(), ex.getFieldError().getDefaultMessage(),
request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

