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
를 통해 다양한 메시지 코드가 순서대로 생성된다.
@NotBlank
NotBlank.item.itemName
NotBlank.itemName
NotBlank.java.lang.String
NotBlank
@Range
Range.item.price
Range.price
Range.java.lang.Integer
Range
이제 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);
}
}
}