특정 필드에 대한 검증 로직은 보통 크기, 타입, null 체크 등이다. 이러한 로직을 매번 작성하기는 코드가 지저분해지고, 반복적인 검증이 많아진다.
이러한 문제를 해결하기 위해 Bean validation(빈 유효성 검사)을 사용한다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
@NotNull, @Size, @NotBlank 등 다양한 검증 애노테이션이 있다.
https://jakarta.ee/specifications/bean-validation/3.0/jakarta-bean-validation-spec-3.0.html
@Valid가 무엇인가?Company를 추가하는 간단한 request dto가 있고, NotNull, NotBlank의 유효성 검사 애노테이션을 적용했다.
public class CompanyRequestDTO {
@NotBlank
private name;
@Notnull
private Address address;
}
그리고 Address와 Car는 값 객체로 아래와 같이 구성했다.
public class Address {
@NotBlank
private String city;
@NotBlank
private String street;
@NotBlank
@Size(max = 10)
private String zipCode;
그리고 Controller 내에 Company 생성 함수 파라미터에 @Valid를 추가하면 정상 작동한다.
@RequiredArgsConstructor
@RestController
@RequestMapping("/companies")
public class CompanyController {
private final CompanyService companyService;
@PostMapping
public ResponseEntity<Object> createCompany(Authentication authentication, @Valid @RequestBody CompanyRequestDTO companyRequestDTO) {
companyService.createCompany(Long.parseLong(authentication.getName()), companyRequestDTO);
return ResponseEntity.status(HttpStatus.CREATED).build();
nested dto를 검증하려면, Address에 @NotNull 대신 @Valid를 붙이면 된다.
public class CompanyRequestDTO {
@NotBlank
private name;
@Valid
private Address address;
}
모든 요청은 dispatcher servlet을 통해 컨트롤러로 전달된다.
이 과정에서 컨트롤러 메서드의 객체를 만들어주는 ArgumentResolver가 동작하는데, @Valid 역시 ArgumentResolver에 의해 처리된다.
또한, 검증에 오류가 생기면 MethodArgumentNotValidException 예외 발생 시켜서 DefaultHandlerExceptionResolber에 의해 400 에러가 발생한다.
@Validated
@Service
public class CompanyService {
public void createCompany(@Valid CompanyRequestDTO companyRequestDTO) {
...
}
}
AOP(Aspect Oriented Programming) 기반으로, 메서드의 요청을 가로채서 유효성 검증이 진행된다.
@Validated를 클래스 레벨에 선언하면, 해당 클래스에 유효성 검증을 위해 AOP에 등록되고MethodValidationInterceptor 클래스에서 가로채서 실행된다.
그리고 유효성 검증에 실패하면, ConstraintViolationException 예외가 발생한다.
참고
@Valid vs @Validated 정리
[SPRING] @Valid 어떻게 동작할까 - java bean validation
[SPRING] @Valid @Validated 사용하기 - java bean validation