Bean Validation

이성준·2022년 3월 13일
0

Spring

목록 보기
2/11

BeanValidation 소개

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;
 //...
}

애노테이션 하나로 검증 로직을 매우 편리하게 적용 가능

  • Bean Validation 이란?
    ->검증 애노테이션과 여러 인터페이스의 모음

스프링 부트는 자동으로 글로벌 Validator로 등록한다.
LocalValidatorFactoryBean 을 글로벌 Validator로 등록한다. 이 Validator는 @NotNull 같은
애노테이션을 보고 검증을 수행한다. 이렇게 글로벌 Validator가 적용되어 있기 때문에, @Valid ,
@Validated 만 적용하면 된다.
검증 오류가 발생하면, FieldError , ObjectError 를 생성해서 BindingResult 에 담아준다. 직접 글로벌 validator를 등록하면 애노테이션 기반의 빈 검증기가 동작 X

검증순서

@ModelAttribute 각각의 필드에 타입 변환 시도
-> 성공하면 다음으로
-> 실패하면 typeMismatch 로 FieldError 추가
2. Validator 적용

Bean Validation - 에러코드


오류 코드가 애노테이션 이름으로 등록된다. NotBlank 라는 오류 코드를 기반으로 MessageCodesResolver 를 통해 다양한 메시지 코드가 순서대로
생성된다. 그래서 자세하게 적고싶으면 레벨 정의하고 메시지를 정의해주면된다.

Bean Validation - 오브젝트 오류

ObjectError 처리하는법
item 에 추가

@ScriptAssert(lang = "javascript", script = "_this.price * _this.quantity >= 10000", message = "총합이 10000원 넘게 해주세요")

실제 사용하기에는 좀 어렵다 그래서 그냥 자바코드로 짜는것을 추천한다.

Bean Validation - 수정에 적용

@PostMapping("/{itemId}/edit")
public String edit(@PathVariable Long itemId, @Validated @ModelAttribute Item
item, BindingResult bindingResult) {
 //특정 필드 예외가 아닌 전체 예외
 if (item.getPrice() != null && item.getQuantity() != null) {
 int resultPrice = item.getPrice() * item.getQuantity();
 if (resultPrice < 10000) {
 bindingResult.reject("totalPriceMin", new Object[]{10000,
resultPrice}, null);
 }
 }
 if (bindingResult.hasErrors()) {
 log.info("errors={}", bindingResult);
 return "validation/v3/editForm";
 }
 itemRepository.update(itemId, item);
 return "redirect:/validation/v3/items/{itemId}";
}
  • 수정에도 검증기능 추가

Bean Validation - 한계

수정시 검증 요구사항
데이터를 등록할 때와 수정할 때는 요구사항이 다를 수 있다.

등록시 기존 요구사항

  • 타입 검증
    가격, 수량에 문자가 들어가면 검증 오류 처리
  • 필드 검증
    상품명: 필수, 공백X
    가격: 1000원 이상, 1백만원 이하
    수량: 최대 9999
  • 특정 필드의 범위를 넘어서는 검증
    가격 * 수량의 합은 10,000원 이상

수정시 요구사항

  • 등록시에는 quantity 수량을 최대 9999까지 등록할 수 있지만 수정시에는 수량을 무제한으로 변경할 수 있다.
  • 등록시에는 id 에 값이 없어도 되지만, 수정시에는 id 값이 필수이다.
@Data
public class Item {
 @NotNull //수정 요구사항 추가
 private Long id;
 @NotBlank
 private String itemName;
 @NotNull
 @Range(min = 1000, max = 1000000)
 private Integer price;
 @NotNull
 //@Max(9999) //수정 요구사항 추가
 private Integer quantity;
 //...
}

그런데 수정은 잘 동작하지만 등록에서 문제가 발생한다.
등록시에는 id 에 값도 없고, quantity 수량 제한 최대 값인 9999도 적용되지 않는 문제가 발생한다.

Form 전송 객체 분리

방법 : Item 사용 x, ItemSaveForm 등 별도 모델 객체 사용

0개의 댓글