Validation (1)

dereck·2025년 2월 4일

TIL

목록 보기
18/21

BindingResult

Spring에서 기본적으로 제공되는 검증 오류를 보관하는 객체로 주로 사용자 입력 폼을 검증할 때 많이 쓰이고 FieldErrorObjectError를 보관한다.

BindingResult docs
바인딩 결과를 나타내는 일반 인터페이스.

오류 등록 기능을 위해 오류 인터페이스를 확장하여 유효성 검사기를 적용할 수 있도록 하고 바인딩별 분석 및 모델 구축을 추가합니다.

DataBinder.getBindingResult() 메서드를 통해 얻은 DataBinder의 결과 홀더 역할을 합니다. 예를 들어 단위 테스트의 일부로 유효성 검사기를 호출하는 등 BindingResult 구현을 직접 사용할 수도 있습니다.

BindingResult는 인터페이스이고, Errors 인터페이스를 상속받고 있다. 실제 넘어오는 구현체는 BeanPropertyBindingResult 라는 것인데, ErrorsBindingResult를 모두 구현하고 있기 때문에 Errors를 사용해도 되지만 BindingResult는 추가 기능들을 제공하기 때문에 BindingResult를 많이 사용한다.

BindingResult가 있으면 @ModelAttribute에 데이터 바인딩 시 오류가 발생해도 컨트롤러가 호출된다.

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

@ModelAttribute에 바인딩 시 타입 오류가 발생하면?

  1. BindingResult가 있을 경우: 오류 정보(FieldError)를 BindingResult에 담아서 컨트롤러를 정상 호출한다.
  2. 400 오류가 발생하면서 컨트롤러가 호출되지 않고, 오류 페이지로 이동한다.

BindingResult에 검증 오류를 적용하는 3가지 방법

  1. @ModelAttribute의 객체에 타입 오류 등으로 바인딩이 실패하는 경우 스프링이 FieldError를 생성해서 BindingResult에 넣어준다.
  2. 개발자가 직접 넣어준다.
  3. Validator 사용

FieldError & ObjectError

FieldError - 필드 오류

// 사용 예시
if(!StringUtils.hasText(item.getItemName())) {
	bindingResult.addError(new FieldError("item", "itemName", "상품 이름은 필수입니다."));
}

// FieldError 생성자 (1)
public FieldError(String objectName, String field, String defaultMessage) { ... }

// FieldError 생성자 (2)
public FieldError(
	String objectName, String field, @Nullable Object rejectedValue, 
    boolean bindingFailure, @Nullable String[] codes, 
    @Nullable Object[] arguments, @Nullable String defaultMessage) { ... }

필드에 오류가 있으면 FieldError 객체를 생성해서 bindingResult에 담아두면 된다.

  • objectName: @ModelAttribute 이름
  • field: 오류가 발생한 필드 이름
  • defaultMessage: 오류 기본 메시지

파라미터 목록은 다음과 같다.

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

ObjectError - 글로벌 오류

// 사용 예시
bindingResult.addError(new ObjectError("item", "가격 * 수량의 합은 10,000원 이상이어야 합니다. 현재 값 = " + resultPrice));

// ObjectError 생성자 (1)
public ObjectError(String objectName, String defaultMessage) { ... }

// ObjectError 생성자 (2)
public ObjectError(
	String objectName, @Nullable String[] codes, 
    @Nullable Object[] arguments, @Nullable String defaultMessage) { ... }

특정 필드를 넘어서는 오류가 있으면 ObjectError 객체를 생성해서 bindingResult에 담아두면 된다.

  • objectName: @ModelAttribute 이름
  • codes: 메시지 코드
  • arguments: 메시지에서 사용하는 인자
  • defaultMessage: 기본 오류 메시지

rejectValue(), reject()

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

rejectValue()

void rejectValue(
	@Nullable String field, String errorCode, 
    @Nullable Object[] errorArgs, @Nullable String defaultMessage);
  • field: 오류 필드명
  • errorCode: 오류 코드
    • 이 오류 코드는 메시지에 등록된 코드가 아니라 messageResolver를 위한 코드임
  • errorArgs: 오류 메시지에서 {0}을 치환하기 위한 값
  • defaultMessage: 오류 메시지를 찾을 수 없을 때 사용하는 기본 메시지
bingResult.rejectValue("price", "range", new Object[]{1000, 1000000}, null)

앞에서 BindingResult는 어떤 객체를 대상으로 검증하는지 target을 이미 알고 있다고 했다. (target 뒤에 BindingResult가 위치하기 때문) 따라서 target에 대한 정보는 없어도 된다.

reject()

void reject(String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage);
  • field: 오류 필드명
  • errorCode: 오류 코드
    • 이 오류 코드는 메시지에 등록된 코드가 아니라 messageResolver를 위한 코드임
  • errorArgs: 오류 메시지에서 {0}을 치환하기 위한 값
  • defaultMessage: 오류 메시지를 찾을 수 없을 때 사용하는 기본 메시지
bingResult.rejectValue("price", "range", new Object[]{1000, 1000000}, null)

0개의 댓글