스프링에서 유효성 검증을 위한 어노테이션으로 @Valid
와 @Validated
를 사용하는데 그 둘의 차이점에 대해 정확하게 파악한 후 사용해야겠다는 생각이 들어 해당 글을 작성하게 되었습니다.
@Valid
는 Bean Validator를 통해 객체의 데이터 유효성 검증을 지시하는 어노테이션입니다. 하지만 이는 Bean Validation의 표준 명세일 뿐 구현체를 가지고 있지는 않습니다. 그래서 구현체를 따로 연결해서 사용해야 합니다.
그래서 Spring에서는 이 구현체를 Hibernate Validator를 사용합니다. Hibernate Validator는 Bean Validator의 모든 어노테이션을 구현하고 있습니다.
따라서 dependency에 아래와 같은 코드를 추가하여 사용합니다.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.1.Final</version>
</dependency>
Client에서 요청이 들어오면 Dispatcher Servlet에서 요청에 맞는 컨트롤러에 요청을 전달합니다.
이때, 전달 과정에서 컨트롤러 메소드의 객체를 전달해주는 HandlerMethodArgumentResolver 동작하는데, @Valid 역시 HandlerMethodArgumentResolver 의해 처리가 됩니다.
HandlerMethodArgumentResolver의 resolveArgument 메소드에서 @Valid로 시작하는 어노테이션이 붙어있으면 dispathcher servlet 단에서 검사 valid를 진행하는 식으로 동작하며, 아래와 같이 검증을 할 파라미터에 @Valid를 붙여줘야 유효성 검증이 진행됩니다.
따라서 Valid 어노테이션은 주로 Controller에서 request body를 검증 하는데 많이 사용됩니다.
@PostMapping("/")
public String doSomething(@Valid Request request) {
...
}
그리고 오류가 발생하면 MethodArgumentNotValidException
이 발생하고, 디스패치 서블릿에 기본으로 등록된 Exception Resolver인 DefaultHandlerExceptionResolver에 의해 400 에러가 발생하게 됩니다.
Spring에서 @Valid는 기본적으로 Controller에서만 동작하도록 설계되어있고 다른 계층에서는 검증이 되지 않기 때문에 다른 계층에서 검증하기 위해서는 @Validated와 결합하여 사용합니다.
@Validated
는 Controller 뿐만 아니라 다른 계층에서도 데이터 유효성 검증을 해야하는 경우 메소드 요청을 가로채서 유효성 검증을 해주는 Spring AOP 기반 기능입니다.
사용법은 아래와 같이 유효성 검증이 필요한 클래스에 @Validated를 붙이고, 유효성 검증을 할 파라미터에 @Valid를 붙이면 동작하게 됩니다.
@Service
@Validated
public class Service {
public void doSomething(@Valid Request request) {
...
}
}
오류가 발생하면 @Valid와 다르게 ConstraintViolationException
이 발생합니다.
@Validated를 클래스에 선언하면 해당 클래스에 유효성 검증을 위한 인터셉터인 MethodValidationInterceptor
가 등록됩니다.
그리고 해당 클래스의 메소드가 호출 될 때 AOP가 포인트컷으로 확인을 하고 요청을 중간에 가로채어 유효성 검증을 진행하게 됩니다.
@Validated
는 Spring의 기능이기 때문에 Spring Bean이라면 모두 유효성 검증이 가능하다는 특징을 가집니다. 그리고 MethodValidationInterceptor에 Validator이 의존성 주입으로 들어가므로 @Valid와 똑같이 Hibernate Validator를 사용하기 때문에 Bean Validation을 그대로 이용할 수 있게 됩니다.
@Valid | @Validated |
---|---|
자바 표준 스펙 javax.validation 패키지에 속함 | 스프링에서 제공하는 어노테이션 org.springframework.validation.annotation에 속함 |
request body 검증 시 사용 | 그룹 유효성 검사나 Controller가 아닌 다른 계층에서 유효성 검증 시 사용 |
MethodArgumentNotValidException 예외 발생 | ConstraintViolationException 예외 발생 |
오 저도 @Valid 와 @Validated의 차이에 대해 이번에 알게되었네요 ❕
마지막에 두 개의 차이를 보기쉽게 정리해주셔서 더 기억에 잘 남을 것 같아요
포스팅 잘 읽었습니다 👍