Dto 또는 객체를 검증하기 위해서 별도의 검증 클래스를 만들어서 Validation을 처리하거나 혹은 표준의 방식을 이용할 수 있다.
@Valid와 @Validated
@Valid
를 이용한 유효성 검증JSR-303 표준 스펙 ( 자바 표준 ) 으로 Bean Validator를 이용해서 객체의 제약 조건을 검증하도록 지시하는 어노테이션이다. 해당 기술의 특징은 객체의 필드에 달린 어노테이션 (NotEmpty , NotNull) 등을 가지고 편리한 검증을 제공한다.
이 기술이 JSR-303 표준 스펙이라는 이야기는 굳이 Spring 프레임워크가 아니더라도 자바 언어 기반이라면 작동한다는 아주 강한 장점을 가지고 있다. ( 근데 어차피 Spring이 최고 아닌가? )
다음과 같이 클래스의 필드에 어노테이션을 각각 추가하여 Validation의 조건을 붙일 수 있다.
public class User {
@NotNull(message = "Name cannot be null")
private String name;
@AssertTrue
private boolean working;
@Size(min = 10, max = 200, message
= "About Me must be between 10 and 200 characters")
private String aboutMe;
@Min(value = 18, message = "Age should not be less than 18")
@Max(value = 150, message = "Age should not be greater than 150")
private int age;
@Email(message = "Email should be valid")
private String email;
// standard setters and getters
}
추가적인 어노테이션은 아래 링크 혹은 자바 표준 문서를 확인하면 알 수 있다.
Http 요청 → 디스패처 서블릿 → 컨트롤러
컨트롤러에서는 객체를 만들어주는 ArgumentResolver 가 동작하는데 Valid 어노테이션 역시 여기서 처리가 된다. @RequestBody
는 Json 메세지를 객체로 변환해주는 작업이 ArgumentResolver의 구현체인 RequestResponseBodyMethodProcessor가 처리하며, 이 내부에서 @Valid로 시작하는 어노테이션이 있을 경우에 유효성 검사를 진행한다. 이러한 이유에서 Custom Valid 어노테이션을 만들 때, Valid로 시작하게 되면 똑같이 작동한다. @RequestBody
가 아닌 @ReuestPart
, @RequsetParam
혹은 default인 @ModelAttribute
를 사용하더라도 각각 MethodProcessor 에 의해 @Valid
어노테이션이 동작한다.
그리고 검증에 오류가 있다면 MethodArgumentNotValidException 예외가 발생하게 되고, 디스패처 서블릿에 기본으로 등록된 예외 리졸버(Exception Resolver)인 DefaultHandlerExceptionResolver에 의해 400 BadRequest 에러가 발생한다.
이러한 이유로 @Valid
는 기본적으로 컨트롤러에서만 동작하며 기본적으로 다른 계층에서는 검증이 되지 않는다.
레퍼런스
[Spring] @Valid와 @Validated를 이용한 유효성 검증의 동작 원리 및 사용법 예시 - (1/2)