티스토리 뷰

Spring

데이터 바인딩 추상화: PropertyEditor

나죽나강 2021. 6. 7. 11:11

데이터 바인딩

  • 기술적 관점 : 프로퍼티 값을 타겟 객체에 설정하는 기능
  • 사용자 관점 : 사용자 입력한 값을 애플리케이션 도메인 모델에 동적으로 변환해 넣어주는 기능

그러면 할당할 때 왜 바인딩이 필요할까?

사용자가 입력한 값은 대부분 문자열인데, 도메인 객체는 int, double, Date 등 Event, Book 같은 도메인 타입 그 자체로 받아야 할 때가 있기 때문이다. 이러한 기능을 제공해주는 org.springframework.validation.DataBinder라는 인터페이스가 있다. 

 

 

PropertyEditor

  • 스프링 3.0 이전까지 DataBinder가 변환 작업 사용하던 인터페이스
  • 쓰레드-세이프 하지 않음(상태 정보 저장 하고 있음 따라서 싱글톤 빈으로 등록해서 사용하면 아주 위험함)
  • Object와 String 간의 변환만 할 수 있어, 사용 범위가 제한적 임 

 

import java.util.StringJoiner;

public class Event {
    private Integer id;
    private String title;

    public Event(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Event.class.getSimpleName() + "[", "]")
                .add("id=" + id)
                .add("title='" + title + "'")
                .toString();
    }
}
import java.beans.PropertyEditorSupport;

public class EventEditor extends PropertyEditorSupport {

    @Override
    public String getAsText() {
        Event event = (Event)getValue();
        return event.getId().toString();
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        setValue(new Event(Integer.parseInt(text)));
    }
}

EventEditor는 PropertyEditorSupport을 상속받아 데이터 바인딩용 클래스이다. setAsText는 사용자가 입력한 데이터를 Event 객체로 변환해 주는 역할을 한다. getAsText는 프로퍼티가 받은 객체를 getValue 메서드를 통해 가져오고 이 Event 객체를 문자열 정보로 변환해서 반환하는 역할을 한다. 그리고 한가지 더 알아두어야 할 점은 getValue()로 가져올 때 타입은 Object이기 때문에 Event로 형변환을 해줘야 한다는 점이다. 아래에서 좀 더 자세히 확인해보자. 

 

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EventController {
 
    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event) {
        System.out.println(event);
        return event.getId().toString();
    }
}

위와 같이 코드가 작성되어 있을 때 GET 방식으로 event/1로 요청이 올 것이다. 이 때 {event}는 int형인 숫자로 넘어오기 때문에 데이터 바인딩이 되어야 에러가 발생하지 않는다. 따라서 위의 setAsText()와 getAsText()를 통해서 데이터 바인딩을 한다. 여기서 중요한점은 PropertyEditorSupport 구현체들은 Thread-safe하지 않는다는 점이다. 따라서 절대 Bean으로 등록해서 사용하면 안된다. 그러면 어떤 방법을 사용해야할까?  

import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EventController {

    @InitBinder
    public void init(WebDataBinder webDataBinder) {
        webDataBinder.registerCustomEditor(Event.class, new EventEditor());
    }

    @GetMapping("/event/{event}")
    public String getEvent(@PathVariable Event event) {
        System.out.println(event);
        return event.getId().toString();
    }
}

위와 같이 @InitBinder 어노테이션을 사용하는 방법이 있다. 지금은 스프링 MVC에 집중된 글이 아니기 때문에 가볍게만 보고 넘어가자. 

 

 

 

 

 

# 인프런 강의 (백기선 / 스프링 프레임워크 핵심 기술)

Resource 추상화  https://joinwithyou.tistory.com/34

Validation 추상화  https://joinwithyou.tistory.com/35

데이터 바인딩 추상화: PropertyEditor  https://joinwithyou.tistory.com/36

데이터 바인딩 추상화: Converter와 Formatter  https://joinwithyou.tistory.com/37

SpEL (스프링 Expression Language)  https://joinwithyou.tistory.com/38

스프링 AOP: 개념 소개  https://joinwithyou.tistory.com/39

스프링 AOP: 프록시 기반 AOP  https://joinwithyou.tistory.com/39

스프링 AOP: @AOP  https://joinwithyou.tistory.com/39

Null-safety  https://joinwithyou.tistory.com/39

 

# Reference

https://devlog-wjdrbs96.tistory.com/165?category=882236 (블로그)

https://www.inflearn.com/course/spring-framework_core (백기선 강의)

'Spring' 카테고리의 다른 글

SpEL (스프링 Expression Language)  (0) 2021.06.07
데이터 바인딩 추상화: Converter와 Formatter  (0) 2021.06.07
[Spring] Validation 추상화  (0) 2021.06.07
[Spring] Resource 추상화  (0) 2021.06.07
IoC 컨테이너 9부: ResourceLoader  (0) 2021.06.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함