- 사용자 입력을 자바 객체로 바인딩하는 기술
- 키는 JavaBean 스타일의 프로퍼티 경로를 따라야 함
1. DataBinder (org.springframework.validation)
- 요청 파라미터를 요청이 담긴 객체에 바인딩하고 검증까지 수행하는 도우미 클래스
| 기능 | 설명 | 비고 | 
| 데이터 바인딩 | Map<String, String[]> 형식의 요청 파라미터를 대상 객체의 필드에 바인딩 | 타입 변환기를 통해 변환  (문자열 → 숫자, 날짜, enum 등) | 
| 유효성 검증 | 등록된 Validator를 이용해 바인딩된 객체 상태를 검사 | binder.validate() 호출  (결과는 BindingResult에 저장) | 
| 에러 결과 관리 | 바인딩/검증 오류 시 FieldError, ObjectError 객체 생성 | BindingResult 안에 담김 (에러 코드도 함께 포함됨) | 
| 메시지 매핑 | 에러 코드 → MessageCodesResolver를 통해 여러 메시지 코드로 확장 | MessageSource에서 가장 구체적인 메시지를 우선적으로 조회 | 
| 컨트롤러 활용 | 컨트롤러 메서드에서 BindingResult를 받아 에러 메시지 처리 가능 | - @InitBinder로 Validator 등록 - 수동으로 DataBinder 사용 | 
2. 바인딩 방식
| 항목 | Constructor Binding | Property Binding | 
| 바인딩 대상 | 생성자 파라미터 | setter | 
| 내부 메커니즘 | 생성자를 통해 객체 생성 | BeanWrapper로 필드 세팅 | 
| 생성자 조건 | 단일 생성자만 존재해야 함 | 필요 없음 | 
| 파라미터 매핑 방식 | 파라미터 이름 기준 (@ConstructorProperties 사용 가능) | 프로퍼티 이름과 setter로 자동 매핑 | 
| 중첩 객체 자동 생성 | ✅ | ✅ | 
| 컬렉션 지원 | ✅ | ✅ | 
| 사용 예 | record, DTO, 불변 객체 | 일반적인 JavaBean, mutable 객체 | 
예제) Constructor Binding
더보기
public class Account {
    private final String name;
    private final int age;
    @ConstructorProperties({"name", "age"}) // 필드의 key 지정
    public Account(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // getter만 존재 (setter 없음)
    public String getName() { return name; }
    public int getAge() { return age; }
}
DataBinder binder = new DataBinder(null); // target 없이 초기화
binder.setTargetType(Account.class); // 대상 타입 설정
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("name", "노아");
pvs.add("age", "29");
Account account = (Account) binder.construct(pvs).getTarget();
System.out.println(account.getName()); // 노아
System.out.println(account.getAge());  // 29
예제) Property Binding
더보기
public class Account {
    private String name;
    private int age;
    public void setName(String name) { this.name = name; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public int getAge() { return age; }
}Account account = new Account(); // 미리 객체 생성
DataBinder binder = new DataBinder(account);
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("name", "노아");
pvs.add("age", "29");
binder.bind(pvs);
System.out.println(account.getName()); // 노아
System.out.println(account.getAge());  // 29
3. BeanWrapper
- JavaBean 객체의 매핑을 지원하는 도구 (프로퍼티의 읽기/쓰기, 중첩 접근, 인덱스 접근 등)
예제
더보기
BeanWrapper company = new BeanWrapperImpl(new Company());
company.setPropertyValue("name", "Some Company Inc.");
company.setPropertyValue("managingDirector.name", "Jim Stravinsky");
Float salary = (Float) company.getPropertyValue("managingDirector.salary");
4. PropertyEditor
- String ↔️ Object 변환기
| 클래스명 | 설명 | 
| ByteArrayPropertyEditor | 문자열 → 바이트 배열 | 
| ClassEditor | 문자열 → Class 객체 | 
| CustomBooleanEditor | 문자열 → Boolean | 
| CustomDateEditor | 문자열 → Date (사용자 정의 포맷 필요) | 
| CustomNumberEditor | 문자열 → 숫자 (Integer, Float 등) | 
| LocaleEditor | 문자열 → Locale | 
| StringTrimmerEditor | 문자열 공백 제거 및 빈 문자열을 null로 변환 | 
Customize
- PropertyEditorSupport 클래스를 상속
- setAsText(String text) 메서드를 오버라이드
- CustomEditorConfigurer 또는 WebDataBinder를 통해 등록
예제
더보기
public class PhoneNumber {
    private String areaCode;
    private String number;
    public PhoneNumber(String areaCode, String number) {
        this.areaCode = areaCode;
        this.number = number;
    }
    public String getAreaCode() { return areaCode; }
    public String getNumber() { return number; }
    @Override
    public String toString() {
        return areaCode + "-" + number;
    }
}public class PhoneNumberEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (text == null || !text.contains("-")) {
            throw new IllegalArgumentException("전화번호 형식이 잘못됨");
        }
        String[] parts = text.split("-");
        if (parts.length != 2) {
            throw new IllegalArgumentException("올바른 전화번호 형식이 아님");
        }
        PhoneNumber phoneNumber = new PhoneNumber(parts[0], parts[1]);
        setValue(phoneNumber);
    }
}class User {
    private PhoneNumber phone;
    public PhoneNumber getPhone() { return phone; }
    public void setPhone(PhoneNumber phone) { this.phone = phone; }
}
User user = new User();
DataBinder binder = new DataBinder(user);
// 📌 커스텀 PropertyEditor 등록
binder.registerCustomEditor(PhoneNumber.class, new PhoneNumberEditor());
// 📌 폼 파라미터처럼 전달된 값
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.add("phone", "010-1234");
binder.bind(pvs);
System.out.println(user.getPhone());  // 010-1234
출처
'Spring > Spring' 카테고리의 다른 글
| [Spring][Validation] 2. Java Bean Validation (0) | 2025.04.06 | 
|---|---|
| [Spring][Validation] 1. Validator (0) | 2025.04.06 | 
| [Spring][Field] 2. Formatting (0) | 2025.04.06 | 
| [Spring][Field] 1. Type Conversion (0) | 2025.04.06 | 
| [Spring][Core] 3-5. Container: Additional Capabilities of the ApplicationContext (0) | 2025.04.06 |