- Spring은 Bean Validation API를 완전하게 지원
1. LocalValidatorFactoryBean
- Spring ↔️ Bean Validation 제공자를 연결해주는 브리지/어댑터 빈
- ✅ Binding: Spring 바인딩 모델 연동 (Errors, BindingResult)
- ✅ i18n: Spring MessageSource 연동
- ✅ 커스텀 검증기 주입: 빈 등록을 통해 추가 가능
- ✅ 제공자 감지: 클래스패스의 기본 Bean Validation 제공자 1개를 자동으로 감지 및 부트스트랩
- ✅ 인터페이스: jakarta.validation.Validator, org.springframework.validation.Validator
설정) LocalValidatorFactoryBean
더보기
@Configuration
public class AppConfig {
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}
- 'hibernate-validator' 의존성이 있으면, 자동으로 등록됨
예제) LocalValidatorFactoryBean 사용
더보기
@Service
public class MyService {
@Autowired
private jakarta.validation.Validator validator;
// private org.springframework.validation.Validator validator; // 이것도 됨
}
메시지 커스터마이징
- Bean Validation 메시지 인터폴레이션을 MessageSource와 연결하기
- ✅ 메시지 키로 에러 메시지를 찾아 i18n/커스터마이즈 가능
흐름) 메시지 인터폴레이션
더보기
- 메시지 템플릿 결정
- 제약 애노테이션의 'message'값 사용
- 비워둘 경우, 표준 기본 메시지를 사용함 (jakarta.validation.constraints.{annotation name}.message)
- 키 해석
- 메시지 소스에서 메시지 템플릿으로 조회
- 파일 이름: ValidationMessages_{locale}.properties, ValidationMessages.properties
- 치환 (인터폴레이션)
- 템플릿 내부의 이름 기반 파라미터를 값으로 대체
- 로케일 선택
- LocaleContextHolder가 현재 Locale로 해당 언어 번들에서 메시지 선택
설정) 메시지 인터폴레이션
더보기
1. 메시지 파일 생성
# src/main/resources/ValidationMessages.properties
Size.person.name=이름은 {2}자 이상 {1}자 이하여야 합니다.
NotBlank.person.name=이름은 필수 항목입니다.
Max.age=나이는 {1} 이하여야 합니다.
- {0}: 필드명
- {1}, {2}: 제약 조건 파라미터
2. 제약 조건 어노테이션에 메시지 키 지정 (@Constraint 속성)
public class Person {
@Size(min = 2, max = 10, message = "{Size.person.name}")
private String name;
@Max(value = 100, message = "{Max.age}")
private int age;
}
- message = "{메시지 키}" 형태로 지정하면 MessageSource에서 해당 메시지를 찾아 사용함.
3. MessageSource 빈 등록하기
@Configuration
public class MessageConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("ValidationMessages"); // 확장자 없이 basename만
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
- 커스터마이징 메시지 프로퍼티를 사용하기 위해 설정 필요
- 다국어 지원 시, ValidationMessages_ko.properties, ValidationMessages_en.properties 등 추가 가능
4. LocalValidatorFactoryBean에 MessageSource 연결
@Bean
public LocalValidatorFactoryBean getValidator(MessageSource messageSource) {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource);
return validator;
}
2. MethodValidationPostProcessor
- 메서드 검증을 켜주는 BeanPostProcessor
- ✅ AOP 기반 동작 (메서드 호출을 프록시가 가로채고, 호출 전/후에 jakarta validator로 유효성 검증)
- ✅ 프록시 (검증 애노테이션을 사용하려는 클래스를 프록시화 함)
- ✅ 어드바이저 부착 (검증 애노테이션을 대상으로 포인트컷이 설정됨. MethodValidationInterceptor가 검증을 담당함)
설정) MethodValidationPostProcessor
더보기
@Configuration
public class ApplicationConfiguration {
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
예시) 사용
더보기
@Service
@Validated
public class MyService {
public void addStudent(@Valid Person person, @Max(2) int degrees) {
// ...
}
@NotNull // 반환값이 null이면 예외 발생
public String getUserName(Long id) {
// DB에서 못 찾았다고 치자
return null;
}
}
MethodValidationInterceptor
- 메서드 검증을 실제로 수행하는 AOP 인터셉터
출처