
해당 포스트는 Spring.io의 공식 문서를 포함한 레퍼런스와 코드를 통해 Spring Framework의 구조 / 기술에 대해 확인해보고자 하는 포스트입니다.
데이터나 입력 값이 정해진 규칙이나 조건을 충족하는지 여부를 판단하는 절차입니다.
데이터 무결성과 보안을 유지하고 시스템의 안정성을 보장하기 위해서 반드시 필요한 절차입니다.
사용자 입력, 데이터베이스, 객체 등과 같이 서로 다른 데이터 소스 간의 데이터를 매핑하거나 연결하는 작업입니다.
데이터의 일관성 및 유효성을 유지하고 데이터를 원하는 형식이나 객체에 적절하기 전달하기 위해 사용됩니다.
서로 다른 데이터 타입 간의 변환을 의미하며 데이터의 일관성과 데이터 처리의 유연성을 위해 필요한 절차입니다.
스프링 프레임워크에서는 위에서 소개한 유효성 검사, 데이터 바인딩, 타입 변환을 기술을 지원합니다.
유효성 검사는 Validator가 있고 데이터 바인딩으로는 DataBinder, BeanWrapper, 타입 변환으로는 PropertyEditor, ConversionService, TypeConverter가 있습니다.
유효성 검사를 담당하는 Validator 인터페이스는 어플리케이션 계층에서 탁월하게 사용할 수 있도록 제공됩니다.
public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
Validator 인터페이스의 구조는 다음과 같으며 메서드에 대한 설명은 다음과 같습니다
support(Class)
제공된 인스턴스에 대한 유효성 검사를 할 수 있는지 여부를 반환
validate(Object, Errors)
해당 객체에 대한 유효성을 검사하고 유효성 검사 오류가 있을 경우 해당 Errors 객체를 등록
이러한 Validator 인터페이스를 구현하여 사용자가 정의한 유효성 검사기를 만들 수 있습니다.
특히 유효성 검사를 할 때 ValidationUtils를 사용하여 쉽게 구현이 가능합니다.
public class PersonValidator implements Validator {
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() < 0) {
e.rejectValue("age", "negativevalue");
} else if (p.getAge() > 110) {
e.rejectValue("age", "too.darn.old");
}
}
Validator와 더불어 validation 패키지에 구성된 DataBinder 인터페이스는 사용자의 입력을 어플리케이션의 도메인 모델이나 사용자 입력을 처리하는데 사용하는 모든 개체에 동적으로 바인딩합니다.
위에서 소개하였듯이 Validator와 같이 사용되어 입력 데이터를 Java 객체로 변환하거나 Java 객체를 웹 폼 등의 입력 필드로 바인딩하고 데이터 변환 및 유효성 검사를 수행합니다.
BeanWrapper는 Java 객체의 속성에 접근하고 조작하는 역할을 하며 주로 객체의 속성에 대한 값을 가져오거나 설정을 할 때 사용됩니다. 주요 기능은 다음과 같습니다.
ListenableBeanWrapper)마찬가지로 데이터 바인딩을 하며, 스프링 프레임워크에서 데이터 바인딩을 지원하기 위해 제공됩니다.
둘 다 데이터 바인딩 처리를 하지만 목적과 상황에 따라 다르게 사용되는 차이점이 있습니다.
DataBinder
주로 웹 어플리케이션에서 사용되며 사용자 입력 데이터와 Java 객체 간의 데이터 바인딩을 수행
(입력 데이터 -> Java 객체로 변환하거나 혹은 Java 객체의 데이터를 입력 데이터 필드에 바인딩)
BeanWrapper
사용자 입력 / 외부 소스로부터 가져온 값을 Java 객체의 속성에 접근하여 설정하거나 객체 속성에 대한 조작을 수행
PropertyEditor는 특정 타입의 프로퍼티 값 <-> 문자열로 변환하는 역할을 하며 주로 DataBinder 에서 사용되어 사용자 입력 데이터의 문자열 값을 객체의 프로퍼티 타입에 맞게 변환할 때 사용합니다.
그러나 최근에는 PropertyEditor 대신 TypeConverter를 사용하는 것을 권장한다고 합니다.
타입 변환을 처리하기 위해 도입된 인터페이스인 Converter는 입력 타입을 지정된 출력 타입으로 변환하는 단순한 변환 로직을 정의하는데 사용합니다.
// Converter 인터페이스
public interface Converter<S, T> {
T convert(S source);
}
// Converter 인터페이스의 구현 사례
final class StringToInteger implements Converter<String, Integer> {
public Integer convert(String source) {
return Integer.valueOf(source);
}
}
ConversionService는 위에서 소개한 TypeConverter, Converter를 여러 개 등록하여 필요한 변환을 자동으로 선택하여 수행할 수 있도록 제공되는 인터페이스입니다.
public interface ConversionService {
boolean canConvert(Class<?> sourceType, Class<?> targetType);
<T> T convert(Object source, Class<T> targetType);
boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}
Java Bean Validation은 자바 기반 어플리케이션에서 데이터의 유효성을 검증하기 위해 사용되며 주로 어노테이션으로 기능을 제공하고 있습니다.
대표적인 어노테이션의 예시는 다음과 같습니다.
@NotNull, @Size, @Pattern, @Min, @Man ...주로 요청에 대한 검증이나 JPA 엔티티와 통합되어 사용되는 편이며 데이터베이스 엔티티의 필드에 제약 조건을 부여하고 저장 및 업데이트 시에 자동으로 유효성을 검증할 수 있습니다.
다만 JSR-380 스펙이기 때문에 JDK 버전이나 JPA와 상관 없는 독립적인 모듈이라 편리하게 사용이 가능하다고 합니다.
유효성 검사와 데이터 바인딩, 타입 변환은 공통적으로 데이터의 일관성과 데이터 처리의 유연성을 위해 반드시 필요한 절차이며 스프링 프레임워크는 이러한 절차들을 위한 기술을 제공합니다.
데이터 바인딩 기술을 위한 대표적인 요소인 BeanWrapper는 Java 객체의 속성에 접근하여 값을 조작할 수 있으며 주로 사용자 입력 데이터나 외부 소스의 데이터를 Java 객체의 속성에 바인딩 시킬 때 사용합니다.
또한 웹 어플리케이션 계층에서 사용자의 입력 데이터의 유효성 검사와 데이터 바인딩을 위한 Validator, DataBinder를 제공하고 있습니다. 이들을 통해 사용자 정의 유효성 검사 로직을 구현하고 사용자의 입력 데이터와 Java 객체 간 데이터 바인딩을 수행할 수 있습니다.
타입 변환을 위한 요소로는 PropertyEditor, TypeConverter, Converter ConversionService가 존재합니다.
마지막으로 Java Bean Validation은 어노테이션을 통해 데이터의 유효성을 검증할 수 있으며 주로 요청에 대한 검증, JPA 엔티티와 같이 사용되어 엔티티 필드의 제약 조건 부여, 유효성 검증에 활용됩니다.
https://docs.spring.io/spring-framework/reference/core/validation.html