기본적인 Validation에 대해서 마지막글인 V5에 대해 포스팅하겠습니다.
이제껏 V4까지는 에러코드를 어떻게 화면에 보여줄지 설명을 햇다면 이번엔 타입오류가 발생했을때 어떻게 처리하면 되는지 설명하는 글이 되겠습니다.
@PostMapping("/add")
public String addItemV4(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes , Model model) {
//검증 로직
if(!StringUtils.hasText(item.getItemName())) { // 상품이름이 없으면
bindingResult.rejectValue("itemName","required");
}
if(item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000){
bindingResult.rejectValue("price","range",new Object[]{1000,1000000},null);
}
if(item.getQuantity()==null|| item.getQuantity() >= 9999) {
bindingResult.rejectValue("quantity","max",new Object[]{9999},null);
}
//특정 필드가 아닌 복합 룰 검증
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/v2/addForm";
}
//성공 로직
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/validation/v2/items/{itemId}";
}
( 코드는 변한게 하나도 없습니다. )
이제까지 적용햇던 Validation으로는 Integer타입인 price와 quantity에 입력폼에 String이 들어오면 대충 타입이 맞지 않는다는 긴 영어의 오류 코드가 나타납니다.
실제로 bindingResult에 담긴 에러들을 아래와 같이 log로 출력해보면 같은 에러코드를 볼수 있다.
if(bindingResult.hasErrors()){
log.info("errors={}", bindingResult);
}
파란색으로 보이는 부분이 price에 대한 타입오류인데 자세히보면 에러에 코드와 해당 에러에 대한 default message가 보인다
에러코드
codes [typeMismatch.item.price,typeMismatch.price,typeMismatch.java.lang.Integer,typeMismatch];
default message
default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'price'; nested exception is java.lang.NumberFormatException: For input string: "qq"
여기서 에러코드는 여태 errors.properties에 등록한 에러 key에 해당이 되는데 해당 파일에 위의 에러코드 4개중 하나만 에러메세지에 넣으면 default message가 아닌 지정한 에러코드가 나오게 된다.
typeMismatch.item.price=가격은 숫자를 입력해주세요.
보기 매우 깔끔해졌습니다. 그런데 price에 에러코드가 두개가 보이는데 컨트롤러로 들어오기전에 bindingResult가 이미 qq라는 값으로 이미 에러를 발생해 값을 가져갔기 때문에 price에 조건절 중 null체크하는 조건에 true가 되어 에러코드가 두개가 들어갔기 때문입니다.
// 해당 코드를 컨트롤러 최상단에 둔다면 price가 null이여서 발생하는 에러코드는 만나지 않고 타입에러만 담고
// 반환을 하게 됩니다.
if(bindingResult.hasErrors()){
return "validation/v2/addForm";
}
여기까지 기본적인 Validation에 대한 포스팅 작성해 보았습니다. 가장 단순한 방법부터 중복과 반복을 줄이고 범용성과 확장성까지 늘려가며 점진적으로 발전하는 Validation에 대한 글이였는데 '김영한'님의 강의에 다시한번 감사함을 느낌니다.
'spring' 카테고리의 다른 글
Spring Boot 메세지, 국제화 (0) | 2024.05.16 |
---|---|
Validation 분리 (0) | 2024.05.15 |
Validation V4 (1) | 2024.05.14 |
Validation V3 (0) | 2024.05.14 |
Validation V2 (0) | 2024.05.13 |