본문 바로가기

Spring/Spring

[Spring] BindingResult / FieldError / ObjectError

반응형

BindingResult는 어떠한 로직을 검증하는 데 쓰이는 인터페이스로 주로 에러가 있는지 확인할 때 쓰인다.

공식 문서를 통해 알아보자.

 

/**
 * General interface that represents binding results. Extends the
 * {@link Errors interface} for error registration capabilities,
 * allowing for a {@link Validator} to be applied, and adds
 * binding-specific analysis and model building.
 *
 * <p>Serves as result holder for a {@link DataBinder}, obtained via
 * the {@link DataBinder#getBindingResult()} method. BindingResult
 * implementations can also be used directly, for example to invoke
 * a {@link Validator} on it (e.g. as part of a unit test).
 *
 * @author Juergen Hoeller
 * @since 2.0
 * @see DataBinder
 * @see Errors
 * @see Validator
 * @see BeanPropertyBindingResult
 * @see DirectFieldBindingResult
 * @see MapBindingResult
 */
 
 public interface BindingResult extends Errors {

	/**
	 * Prefix for the name of the BindingResult instance in a model,
	 * followed by the object name.
	 */
	String MODEL_KEY_PREFIX = BindingResult.class.getName() + ".";

 

BindingResult 인터페이스

1.  바인딩 결과를 나타내는 인터페이스로 오류 등록 기능을 위해 Errors 인터페이스를 상속받는다.

2. @Validator 인터이스를 적용하고 바인딩 분석과 모델 빌딩을 추가한다.

 

아래는 주로 많이 쓰이는 FieldError에 관한 예제이다.

 @PostMapping("/add")
    public String addItemV1(@ModelAttribute Item item, BindingResult bindingResult, RedirectAttributes redirectAttributes, Model model) {


        //검증 로직
        if (!StringUtils.hasText(item.getItemName())) {
            bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다"));
            // objectName은 modelAttribute 이름, field는 필드명
        }

우선 BindingResult는 검증할 대상 바로 다음에 와야 하기 때문에 우리가 검증할 객체인 @ModelAttribute item객체 바로 다음에 와야 한다.

조금 더 자세히 알아보기 위해 FieldError를 분석해보자.

 

FieldError는 파라미터로 objectName, field, defaultMessage를 받는다.

1. objectName : @ModelAttribute Item item 객체를 넣어주면 된다.

2. field : 1번에서 item 객체에 이 bindingresult를 넣어주면 HTML 코드에서 타임리프 문법인 th:field="*{itemName}"으로 필드를 찾기 때문에 타임리프 필드명을 넣어주면 된다.

   <label for="itemName" th:text="#{label.item.itemName}">상품명</label>
            <input type="text" id="itemName" th:field="*{itemName}"
                  th:errorclass="field-error" class="form-control" placeholder="이름을 입력하세요">
            <div class="field-error" th:errors="*{itemName}">
                상품명 오류

3.defaultMessage : 오류가 났을 때 나오는 메시지를 입력해준다.

 


 

if (item.getPrice() != null && item.getQuantity() != null) {
            int resultPrice = item.getPrice() * item.getQuantity();
            if (resultPrice < 10000) {
                bindingResult.addError(new ObjectError("item","가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice ));
                // 특정 필드에 대한 오류가 아닌 글로벌 오류라서 ObjectError에 담는다.
            }
        }

글로벌 에러인 경우에는 objectError를 사용한다. 이때 FieldError와의 차이점은 objectError는 어떠한 필드에 들어가지는 않기 때문에 filed명을 제외한 objectName, defaultMessage 두 가지를 파라미터로 갖는다.

(참고로 FieldError는 objectError를 상속받는다.)

 

코드 출처 : 인프런 - 스프링 MVC 2편

반응형