티스토리 뷰
데이터 바인딩
- 기술적 관점 : 프로퍼티 값을 타겟 객체에 설정하는 기능
- 사용자 관점 : 사용자 입력한 값을 애플리케이션 도메인 모델에 동적으로 변환해 넣어주는 기능
그러면 할당할 때 왜 바인딩이 필요할까?
사용자가 입력한 값은 대부분 문자열인데, 도메인 객체는 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 |
