오류 코드와 메세지 처리2

shinyeongwoon·2023년 1월 27일
0

Message

목록 보기
7/11

목표
FieldError, ObjectError는 다루기 너무 번거롭다.
오류 코드도 좀 더 자동화 할 수 있지 않을까? ex) item.itemName 처럼?

컨트롤러에서 BindingResult는 검증해야 할 객체인 target바로 다음에 온다.
따라서 BindingResult는 이미 본인이 검증해야할 객체인 target을 알고 있다.

다음을 컨트롤러에서 실행해 보자.

log.info("objectName={}",bindingResult.getobjectName());
log.info("target={}",bindingResult.getTarget());

출력 결과

objectName=item //@ModelAttrivute name
target=Item(id=null,itemName=상품,price=100, quantity=1234)

RejectValue(),reject()

BindingResult가 제공하는 rejectValue(),reject()를 사용하면 FieldError,ObjectError를 직접 생성하지 않고, 깔끔하게 검증 오류를 다룰 수 있다.

rejectValue(),reject()를 사용해서 기존 코드를 단순화해보자

ValidationItemControllerV2-addItemV4() 추가

@PostMapping("/add")
public String addItemV4(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes){
	log.info("objectName={}",bindingResult.getObjectName());
    log.info("target={}", bindingResult.getTarget());
    
    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() > 10000){
    	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}";

}

실행

오류 메세지가 정상 출력 된다. 그런데 errors.properties에 있는 코드를 직접 입력하지 않았는데 어떻게 된 것일까?

rejectValue()

void rejectValue(@Nullable String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String sefaultMessage);

filed : 오류 필드명
errorCode : 오류 코드 (이 오류 코드는 메세지에 등록된 코드가 아니다. 뒤에서 설명할 messageResolver를 위한 오류 코드 이다.)
errorArgs: 오류 메세지에서 {0}을 치환하기 위한 값
defaultMessage: 오류 메세지를 찾을 수 없을때 사용하는 기본 메세지

bindingReuslt.rejectValue("price","range",new Object[]{1000,1000000},null);

앞에서는 BindingResult는 어떤 객체를 대상으로 검증하는지 target을 이미 알고 있다고 했다. 따라서 target(item)에 대한 정보는 없어도 된다. 오류 필드명은 동일하게 price를 사용했다.

축약된 오류 코드

FieldError()를 직접 다룰때는 오류 코드를 range.item.price와 같이 모두 입력했다.
그런데 rejectValue() 를 사용하고 부터는 오류코드를 range로 간단하게 입력했다. 그래도 오류 메세지를 잘 찾아서 출력한다. 무언가 규칙이 있는 것 처럼 보인다. 이부분을 이해하려면
MessageCodesResolver를 이해해야 한다. 왜 이런식으로 오류 코드를 구성하는지 바로 다음에 자세하게 알아보자

errors.properties

range.item.price=가격은 {0} ~ {1} 까지 허용합니다.

reject()

void reject(String errorCode,@Nullable Object[] errorArgs,@Nullable String defaultMessage);

앞의 내용과 같다.

0개의 댓글