Spring/Spring

[Spring][Object] 1. Data Binding

noahkim_ 2025. 4. 6. 21:32

1. Data Binding

  • Map 형태의 사용자 입력을 자바 객체로 바인딩하는 기술
  • DataBinder 클래스를 통해 구현됨
  • 키는 JavaBean 스타일의 프로퍼티 경로를 따라야 함

 

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

 

  1. PropertyEditorSupport 클래스를 상속
  2. setAsText(String text) 메서드를 오버라이드
  3. 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

 


출처