BindingResult

  • Spring이 제공하는 검증 오류 처리 기능

  • 방법

    1. @ModelAttribute의 객체 타입 오류 등으로 바인딩 실패 시, Spring이 FieldError 자동 생성 후 BindingResult에 넣어줌
    2. 개발자가 직접 넣음
    3. Validator 사용
  • 주의 사항

    • BIndingResult는 검증 대상 바로 다음에 작성해야함

    • public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model)
      
    • 위의 코드에서 보면 Item 객체가 검증 대상이므로 그 다음에 바로 BindingResult 작성
  • addError 메소드를 이용하여 FieldError와 ObjectError를 추가할 수 있음

FieldError

  • 두가지 생성자 제공
  • public FieldError(String objectName, String field, String defaultMessage) {
    	this(objectName, field, null, false, null, null, defaultMessage);
    }
      
    public FieldError(String objectName, String field, @Nullable Object rejectedValue, boolean bindingFailure,
    	@Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage) {
      
    	super(objectName, codes, arguments, defaultMessage);
    	Assert.notNull(field, "Field must not be null");
    	this.field = field;
    	this.rejectedValue = rejectedValue;
    	this.bindingFailure = bindingFailure;
    }
    
  • 파라미터 목록

    • objectName : 오류가 발생한 객체 이름 (@ModelAttribute에 담기는 이름)
    • field : 오류 필드 (필드명)
    • rejectedValue : 사용자가 입력한 값 (거절된 값) => 사용 시 에러 발생해도 필드값 유지
    • bindingFailure : 타입 오류 같은 바인딩 실패인지, 검증 실패인지 구분
    • codes : 메세지 코드
    • arguments : 메세지에서 사용하는 인자
    • defaultMessage : 기본 오류 메세지

ObjectError

  • 데이터가 넘어와서 처리되는 에러가 아니므로 기존 데이터를 보관할 필요가 없음
  • 즉, 바인딩을 실패할 일이 없음 (벌써 넘어온 필드 데이터를 조합하는 것)
  • 따라서 파라미터 목록에 rejectedValue, bindingFailure가 없음

codes, arguments 파라미터를 활용하여 error 관리

  • IDE의 기본 Encoding값이 UTF-8인지 확인 필수

  • errors.properties로 error 포괄적인 관리 가능

  • /resources/apllication.properties에 아래 코드추가

    • spring.messages.basename=messages,errors (메세지, 에러 둘 다 사용)
    • 생략 시 default로 messages.properties 읽어들임
    • errors를 추가하여 errors.properties 읽어들임
    • [에러 메세지 생성 규칙]

codes 파라미터

  • String[] 으로 값을 받음
    • 하나의 에러 코드가 아닌 여러 에러 코드를 검토할 수 있음
  • errors.properties에 지정해준 error code Name으로 지정

arguments 파라미터

  • Object[] 으로 값을 받음
    • 여러 파라미터를 전달할 수 있음
  • errors.properties에서 파라미터 값을 전달할 때, 그 순서에 맞게 입력

예시

# errors.properties
# ErrorCode명.Object명.Field명
range.item.price=가격은 {0} ~ {1} 까지 허용합니다.
# 에러 처리 부분
bindingResult.addError(new FieldError("item", "price", item.getPrice(), true, new String[]{"range.item.price"}, new Object[]{1000, 1000000}, null));
  • codes : new String[]{“range.item.price”}
  • arguments : new Object[]{1000, 1000000} => {0}, {1}에 각각 대입

reject(), rejectValue()를 활용하여 간소화

  • BindingResult는 검증 대상 객체(여기선 Item)을 이미 알고 있음
    • reject() - ObjectError
    • rejectValue() - FieldError
    • 위 두가지로 더 간소화할 수 있음
  • 기존 코드 예시
# FieldError 
bindingResult.addError(new FieldError("item", "price", item.getPrice(), true, new String[]{"range.item.price"}, new Object[]{1000, 1000000}, null));

# Object Error
bindingResult.addError(new ObjectError("item", new String[]{"totalPriceMin"}, new Object[]{10000, resultPrice}, null)); 
  • reject(), rejectValue() 사용
# FieldError => rejectValue()
bindingResult.rejectValue("price", "range", new Object[]{1000, 1000000}, null);

#Object Error => reject()
bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
  • 변경 사항
    • 검증 대상을 미리 알고 있으므로 objectName(“item”) 사용 X
    • rejectedValue 파라미터 필요 X
    • 기존 codes => errorCode 변경 (MessageCodeResolver 참고)

MessageCodesResolver

  • 검증 오류 코드로 메세지 코드들을 생성
  • 주로 DefaultMessageCodesResolver 구현체 사용
  • 기본 메세지 생성 규칙 (구체적 -> 범용적)
    • 객체 오류
      1. code + “.” + object name
      2. code
    • 필드 오류
      1. code + “.” + object name + “.” + field
      2. code + “.” + field
      3. code + “.” + field type
      4. code
  • FieldError, ObjectError의 생성자에서, 오류 코드는 String 배열로 여러가지를 가질 수 있었음
  • MessageCodesResolver가 위의 생성 규칙의 순서에 맞게 오류 코드들을 보관함
  • 구체적 -> 범용적으로 내려가면서 일치하는 오류 메세지에 맞게 오류를 최종적으로 출력해줌

Spring이 직접 처리하는 에러 메세지 수정

  • 데이터의 타입이 불일치하는 것과 같은 에러들은 Spring이 알아서 에러를 처리해줌

  • 이 때, Spring이 뿌리는 default message는 사용자가 보아서 좋을 것이 없음

  • 이런 경우의 에러들 또한 errors.properties에서 개발자가 직접 정의해줄 수 있음

  • # typeMismatch 에러 발생 (숫자에 문자를 입력함)
    Field error in object 'item' on field 'price': rejected value [A]; codes [typeMismatch.item.price,typeMismatch.price,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [item.price,price]; arguments []; default message [price]]; 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: "A"]
    
  • # errors.properties에 추가
    typeMismatch.java.lang.Integer=숫자를 입력해주세요.
    typeMismatch=타입 오류입니다.
    



인프런 - 김영한님의 Spring MVC 강의를 정리한 내용입니다.


김영한님 인프런 강의

댓글남기기