지금까지 BingingResult를 통해 Controller 실행까지 들어가서 어떤 오류인지 잡고, 사용자 오류 값도 처리하고 잘 했었다. 근데!! 오류 코드나 메시지 처리가 너무 개발자 스럽다!! 즉 사용자에겐 불친절 하다!
application.properties(yaml)에 message의존성 추가하고 resources에 해당 메시지내용 추가해놓고
application.properties에 의존성 추가
spring.messages.basename=messages,errors
src/main/resources/errors.properties 오류메시지 내용 추가.
required.item.itemName=상품 이름은 필수입니다.
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
max.item.quantity=수량은 최대 {0} 까지 허용합니다.
totalPriceMin=가격 * 수량의 합은 {0}원 이상이어야 합니다. 현재 값 = {1}
아래 코드처럼 매개변수 “code”에 해당하는 내용에 String배열 형으로 원하는 오류메시지를 넣을 수 있다. 그리고 매개변수 “argument”에 해당하는 곳에 properties문법(like {0},{1} ) 해당하는 매개변수를 넣어서 원하는 오류 메시지를 좀 더 유동적으로 쓸 수 있다.
//    @PostMapping("/add")
    public String addItemV3(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {
        //검증 로직
        if (!StringUtils.hasText(item.getItemName())) {
            bindingResult.addError(new FieldError("item", "itemName", item.getItemName(), false, new String[]{"required.item.itemName"}, null, null));
        }
        if (item.getPrice() == null || item.getPrice() < 1000 || item.getPrice() > 1000000) {
            bindingResult.addError(new FieldError("item", "price", item.getPrice(), false, new String[]{"range.item.price"}, new Object[]{1000, 1000000}, null));
        }
        if (item.getQuantity() == null || item.getQuantity() >= 9999) {
            bindingResult.addError(new FieldError("item", "quantity", item.getQuantity(), false, new String[]{"max.item.quantity"} ,new Object[]{9999}, null));
        }
        //특정 필드가 아닌 복합 룰 검증
        if (item.getPrice() != null && item.getQuantity() != null) {
            int resultPrice = item.getPrice() * item.getQuantity();
            if (resultPrice < 10000) {
                bindingResult.addError(new ObjectError("item",new String[]{"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}";
        }
근데!!@@ FiledError랑 ObjectError는 다뤄야할 매개변수도 너무 많고 복잡하다!! 뭔가 오류 코드도 자동화 할 방법이 없을까??
사실 컨트롤러에서 BindingResult는 검증해야 할 객체인 target 바로 다음에 온다! 따라서 BindingResult는 이미 본인이 검증해야 할 객체인 target(@ModelAttribute로 바인딩된 객체 자체)를 알고 있다!
slj4로 로그 찍어보면 진짜 target을 알고 있음.

BindingResult가 제공하는 rejectValue(), reject()를 사용하면 FiledError, ObjectError를 직접 생성하지 않고 깔끔하게 검증오류를 다룰 수 있다! (사실 각각 파고들어가보면 결국 FiledError, ObjectError를 생성하고 있다.)