@Valid
와 @Validated
의 차이점을 이해한다.@Valid
와 @Validated
의 사용법을 이해한다.
공통점#
- 컨트롤러 파라미터에
@Valid
, @Validated
를 붙이면, 글로벌 Validator
로 검증이 된다. - Spring Boot는 JSR-380의 기본 구현인 Hibernate Validator를 글로벌
Validator
로 사용한다.
컨트롤러에서 @Valid vs @Validated#
@Valid
는JSR-303의 어노테이션으로 메서드 수준의 유효성 검사에 사용한다.@Validated
는 Spring에서 @Valid
를 확장하기 위해 만든 어노테이션이다.@Validated
는 validation group이라는 기능을 제공한다.- 컨트롤러에서는 validation group 기능 유무 차이가 존재한다.
- 컨트롤러에서
@ReqeustBody
, @ModelAttribute
, @RequestPart
가 붙어있는 파라미터는 ArgumentResolver
에서 처리되며, @Valid
나 @Validated
가 있을 때 검증 실패시 MethodArgumentNotValidException
예외가 발생한다. - 아래 사진은
ArgumentResolver
의 구현체들에서 사용하고 있는 ValidationAnnotationUtils
코드의 일부다.
@Valid 어노테이션 사용 예#
- 아래의
@NotBlank
, @Min
어노테이션은 Java Bean Validation 에서 제공하는 어노테이션이다.
public class UserAccount {
@NotNull
@Size(min = 4, max = 15)
private String password;
@NotBlank
private String name;
@Min(value = 18, message = "Age should not be less than 18")
private int age;
@NotBlank
private String phone;
// standard constructors / setters / getters / toString
}
@RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
public String saveBasicInfo(
@Valid @ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result,
ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
@Validated 어노테이션 사용 예#
@Validated
를 사용하면, 각 검증 어노테이션을 그룹으로 만들 수 있다.@Validated
애노테이션에 그룹을 나타내는 인터페이스 클래스 타입을 인자로 넘긴다.
public class UserAccount {
@NotNull(groups = BasicInfo.class)
@Size(min = 4, max = 15, groups = BasicInfo.class)
private String password;
@NotBlank(groups = BasicInfo.class)
private String name;
@Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
private int age;
@NotBlank(groups = AdvanceInfo.class)
private String phone;
// standard constructors / setters / getters / toString
}
@RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
public String saveBasicInfoStep1(
@Validated(BasicInfo.class)
@ModelAttribute("useraccount") UserAccount useraccount,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
@Validated의 Method Validation#
@Validated
어노테이션은 Spring의 Method Validation 기능을 사용할 때도 사용된다.- 클래스 레벨에
@Validated
를 붙이고, 메서드 파라미터에 @Min
등의 유효성 검사 어노테이션을 붙이거나, @Valid
를 붙이면 검증이 메서드 파라미터에서 유효성 검사가 된다. - 이 때 유효성 검사를 실패하면
ConstraintViolationException
이 발생한다. - Spring의 Method Validation은 AOP 기반으로 메소드 요청을 인터셉트하여 처리된다.
@Service
@Validated
public class UserService {
public void addUser(@Valid AddUserRequest addUserRequest) {
...
}
}
Spring Framework 6.1(Spring Boot 3.2)의 변화점#
- 기존에 Controller에서는 ArgumentResolver가 validation을 처리했기 때문에,
@PathVaraible
이나 @RequestParam
으로 아래와 같은 검증은 불가능했다.
@RestController
class UserController {
@GetMapping("/users")
public String hello(@RequestParam @Length(min = 10) String name){
return name;
}
}
- Spring Framework 6.1부터
RequestMappingHandlerAdapter
에 Controller의 파라미터에 대한 validator를 등록할 수 있게 되면서, 위 예시에 대한 validation은 @Valid
나 @Validated
없이도 검증을 수행한다. - 이 때 실패한 검증은
HandlerMethodValidationException
예외가 발생한다. - 아래는
RequestMappingHandlerAdapter
내 메소드다.
참고 자료#