
Bean Validation - 소개지난 시간에 개발했던 검증 로직은 다음과 같은 특징을 갖는다.
null) 값인지 체크이런 검증 로직을 모든 프로젝트에 적용할 수 있게 공통화/표준화한 것이
Bean Validation이다.
Bean Validation은특정한 구현체가 아닌,
Bean Validation 2.0 (JSR-380)이라는 기술 표준
Bean Validation은 검증 애노테이션과 여러 인터페이스의 모음으로,
이를 통해 애노테이션 하나로 검증 로직을 매우 편리하게 적용할 수 있다.
Bean Validation - 시작우리 프로젝트에 적용하기 전에,
순수한 Bean Validation 사용법에 대해 먼저 알아보자!
Bean Validation 의존관계 추가Bean Validation을 사용하려면 의존관계를 추가해야 한다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
Item - Bean Validation 애노테이션 적용@Data
public class Item {
private Long id;
@NotBlank
private String itemName;
@NotNull
@Range(min = 1000, max = 1000000)
private Integer price;
@NotNull
@Max(9999)
private Integer quantity;
...
}
@NotBlank: 빈값 + 공백만 있는 경우를 허용하지 않는다.@NotNull: null을 허용하지 않는다.@Range(min = 1000, max = 1000000): 범위 안(1000 이상, 1000000 이하)의 값이어야 한다.@Max(9999): 최대 9999까지만 허용한다.
Bean Validation - 프로젝트 준비 V3🔗 코드 확인하기

Bean Validation - 스프링 적용MVC의 Bean Validator 사용법스프링 부트는 spring-boot-starter-validation 라이브러리를 넣으면 자동으로 Bean Validator를 인지하고 스프링에 통합한다!
Validator로 등록한다.Validator가 적용되어 있기 때문에, @Valid,@Validated만 적용하면 된다.FieldError, ObjectError를 생성해서 BindingResult에 담아준다.📌 검증 순서
@ModelAttribute각각의 필드에 타입 변환 시도
- 성공하면 다음으로
- 실패하면
typeMismatch로FieldError추가Validator적용
⭐ 바인딩에 성공한 필드만
Bean Validation을 적용한다.

Bean Validation - 에러 코드Bean Validation이 기본으로 제공하는 오류 메시지 변경만약 Bean Validation이 기본으로 제공하는 오류 메시지를 좀 더 자세히 변경하고 싶으면 어떻게 하면 될까?
Bean Validation을 적용하고 bindingResult에 등록된 검증 오류 코드를 보면,
마치 typeMismatch처럼 NotBlank라는 오류 코드를 기반으로 MessageCodesResolver를 통해 다양한 메시지 코드가 순서대로 생성된다.
@NotBlankNotBlank.item.itemNameNotBlank.itemNameNotBlank.java.lang.StringNotBlank@RangeRange.item.priceRange.priceRange.java.lang.IntegerRange이제 typeMismatch처럼, 우리가 원하는 형태로 출력되도록 메시지를 등록해보자.
errors.properties#Bean Validation 추가
NotBlank={0} 공백X
Range={0}, {2} ~ {1} 허용
Max={0}, 최대 {1}
{0}은 필드명{1}, {2} ...은 각 애노테이션 마다 다르다.Bean Validation 메시지 찾는 순서messageSource에서 메시지 찾기message 속성 사용 → @NotBlank(message = "공백! {0])
Bean Validation - 오브젝트 오류이번에는 특정 필드(FieldError)가 아닌 오브젝트 관련 오류(ObjectError) 처리 방법에 대해 알아보자!
@ScriptAssert
@ScriptAssert()를 사용하여 해결할 수 있다!
@Data
@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000")
public class Item {
//...
}
실행해보면 정상적으로 수행되며, 메시지 코드도 다음과 같이 생성된다.
ScriptAssert.item
ScriptAssert
하지만 실제 사용해보면 제약이 많고 복잡하다.
그리고 실무에서는 검증 기능이 해당 객체의 범위를 넘어서는 경우도 종종 등장하여, 그런 경우 대응이 어렵다.
그래서 오브젝트 오류(글로벌 오류)의 경우는 @ScriptAssert을 억지로 사용하는 것보다는
다음과 같이 오브젝트 오류 관련 부분만 직접 자바 코드로 작성하는 것을 권장한다.
@PostMapping("/add")
public String addItem(@Validated @ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
//특정 필드가 아닌 복합 룰 검증
if (item.getPrice() != null && item.getQuantity() != null) {
int resultPrice = item.getPrice() * item.getQuantity();
if (resultPrice < 10000) {
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
}
}
}


