Spring/Spring

[Spring][Validation] 1. Validator

noahkim_ 2025. 4. 6. 21:33

1. Validator 인터페이스 (org.springframework.validation)

  • 특정 타입의 상태를 검사하는 전용 검증기 인터페이스
  • ✅ 스프링 프레임워크 내부 바인딩/폼 검증을 위해 사용됨 (Spring MVC, DataBinder 등)

 

코드

더보기
public interface Validator {
    boolean supports(Class<?> clazz);
    void validate(Object target, Errors errors);
}
메서드명 설명 특징
supports(Class<?> clazz) 검증 대상 타입 확인 특정 클래스 타입을 검증할 수 있는지 여부
validate(Object target, Errors errors) 실제 검증 로직 수행 Errors 객체 제공
(검증 중 발생한 오류를 수집함)

 

예제) 객체

더보기
public class PersonValidator implements Validator {
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz); // Person 타입만 검증
    }

    public void validate(Object obj, Errors e) {
        ValidationUtils.rejectIfEmpty(e, "name", "name.empty"); // name 필드 비었는지 확인
        Person p = (Person) obj;
        if (p.getAge() < 0) {
            e.rejectValue("age", "negativevalue");
        } else if (p.getAge() > 110) {
            e.rejectValue("age", "too.darn.old");
        }
    }
}
ValidationUtils 메서드 설명
rejectIfEmpty()
특정 필드가 null 또는 "" (빈 문자열)이면 에러로 등록
rejectIfEmptyOrWhitespace()
특정 필드가 null, "", 또는 공백 문자만 있으면 에러로 등록
invokeValidator()
다른 Validator를 호출해서 하위 객체를 검증 (중첩 검증 시 사용)

 

예제) 복합 객체

더보기
public class CustomerValidator implements Validator {

    private final Validator addressValidator;

    public CustomerValidator(Validator addressValidator) {
        if (addressValidator == null || !addressValidator.supports(Address.class)) {
            throw new IllegalArgumentException("Validator가 Address 검증을 지원해야 합니다.");
        }
        this.addressValidator = addressValidator;
    }

    public boolean supports(Class clazz) {
        return Customer.class.isAssignableFrom(clazz); // Customer 혹은 그 하위 클래스
    }

    public void validate(Object target, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");

        Customer customer = (Customer) target;

        try {
            errors.pushNestedPath("address");
            ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
        } finally {
            errors.popNestedPath();
        }
    }
}
ValidationUtils 메서드 설명
rejectIfEmpty()
특정 필드가 null 또는 "" (빈 문자열)이면 에러로 등록
rejectIfEmptyOrWhitespace()
특정 필드가 null, "", 또는 공백 문자만 있으면 에러로 등록
invokeValidator()
다른 Validator를 호출해서 하위 객체를 검증 (중첩 검증 시 사용)

 

2. 예외 인터페이스

Errors

  • Spring MVC 바인딩 및 검증 오류 정보를 담는 최상위 인터페이스
  • ✅ 필드별/글로벌 오류 등록
  • ✅ 에러 메시지/코드 저장

예제) 에러 코드를 메시지로 변환하기

더보기

1. 유효성 검증 실패 처리 - rejectValue()

errors.rejectValue("age", "too.darn.old");
  • 에러 코드는 "too.darn.old"

 

2.에러 코드를 바탕으로 여러 메시지 코드를 등록 - MessageCodesResolver (DefaultMessageCodesResolver)

  • 에러 코드를 어떻게 변환할지 결정함
  • ✅ 필드 에러: errorCode.objectName.field, errorCode.field, errorCode.fieldType, errorCode
  •  오브젝트 에러: errorCode.objectName, errorCode
  • ➡️ MessageSource가 메시지를 유연하게 매칭할 수 있도록 함

 

3. 메시지 매핑 우선순위

too.darn.old.user.age=사용자 나이 제한을 초과했습니다.   # 최우선
too.darn.old.age=나이가 너무 많습니다!
too.darn.old.int=나이가 너무 많습니다! (int)
too.darn.old=나이 제한 오류입니다.
  • Spring은 위 코드 목록 순서대로 메시지를 찾다가, 가장 먼저 매칭되는 메시지를 반환함
  • ➡️ too.darn.old.age.user.int가 가장 우선해서 매칭됨

 

3. 헬퍼 클래스

ValidationUtils

  • Errors 객체를 쉽게 다루기 위해 제공되는 헬퍼 클래스 (정적 메서드 제공)
  • Validator 내에서 필수 값 검증 시 사용
  • ✅ 빈값/공백 검증
  •  반복 로직 추상화 (다른 Validator 호출 등)

 

예제) ValidationUtils

더보기
public void validate(Object obj, Errors errors) {
    ValidationUtils.rejectIfEmpty(errors, "name", "name.empty");
}
if (target.getName() == null || target.getName().isEmpty()) {
    errors.rejectValue("name", "name.empty");
}
  • 위 코드와 같은 패턴을 래핑해서 더 간결하게 쓸 수 있도록 도와줌

 

4. DataBinder와 Validator 수동 사용

  • 보통 컨트롤러 단에서는 자동으로 WebDataBinder가 데이터 바인딩을 해줌
  • ✅ DataBinder를 통해 수동으로 바인딩 + 유효성 검증 가능
  •  여러 Validator를 조합할 수도 있음 (addValidators, replaceValidators)

 

예시

더보기
Foo target = new Foo();
DataBinder binder = new DataBinder(target);
binder.setValidator(new FooValidator());

binder.bind(propertyValues);
binder.validate();

BindingResult results = binder.getBindingResult();

 

출처

'Spring > Spring' 카테고리의 다른 글

[Spring][AOP] 1. Advice API  (0) 2025.04.09
[Spring][Validation] 2. Java Bean Validation  (0) 2025.04.06
[Spring][Object] 1. Data Binding  (0) 2025.04.06
[Spring][Field] 2. Formatting  (0) 2025.04.06
[Spring][Field] 1. Type Conversion  (0) 2025.04.06