이런 검증 로직을 모든 프로젝트에 적용할 수 있게 공통화하고, 표준화 한 것이 바로 Bean Validation 이다. Bean Validation을 잘 활용하면, 애노테이션 하나로 검증 로직을 매우 편리하게 적용할 수 있다

Jakarta Bean Validation

jakarta.validation-api: Bean Validation 인터페이스 hibernate-validator 구현체

implementation 'org.springframework.boot:spring-boot-starter-validation'
@Data
//@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000")
public class Item {

    //@NotNull(groups = UpdateCheck.class)
    private Long id;

  //  @NotBlank(groups = {SaveCheck.class, UpdateCheck.class})
    private String itemName;

    //@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
    //@Range(min = 1000, max = 1000000, groups = {SaveCheck.class, UpdateCheck.class})
    private Integer price;

    //@NotNull(groups = {SaveCheck.class, UpdateCheck.class})
    //@Max(9999)
    private Integer quantity;

    public Item() {
    }

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }
}

스프링 MVC는 어떻게 Bean Validator를 사용?

스프링 부트가 spring-boot-starter-validation 라이브러리를 넣으면 자동으로 Bean Validator를 인지하고 스프링에 통합한다.

스프링 부트는 자동으로 글로벌 Validator로 등록한다.

LocalValidatorFactoryBean 을 글로벌 Validator로 등록한다. 이 Validator는 @NotNull 같은 애노테이션을 보고 검증을 수행한다.

이렇게 글로벌 Validator가 적용되어 있기 때문에, @Valid ,@Validated 만 적용하면 된다.

검증 오류가 발생하면, FieldError , ObjectError 를 생성해서 BindingResult 에 담아준다.

둘중아무거나 사용해도 동일하게 작동하지만, @Validated 는 내부에 groups 라는 기능을 포함하고 있다. 이부분은 조금 뒤에 다시 설명하겠다.

Bean Validation - 에러 코드

BeanValidation 메시지 찾는 순서

  1. 생성된 메시지 코드 순서대로 messageSource 에서 메시지 찾기
  2. 애노테이션의 message 속성 사용 @NotBlank(message = "공백! {0}")
  3. 라이브러리가 제공하는 기본 값 사용 공백일 수 없습니