오늘은 스프링에서 자주 사용하는 Model 객체와 ModelMap 객체에 대해서 포스팅 해보겠다.
Model만 있는 줄 알았는데 ModelMap 이라는 객체도 있었다.
1. 스프링에서 Model 객체란?
스프링에서는 Controller 의 메소드들이 받는 파라미터(Argument)들을 관리하는 ArgumentResolver 가 존재한다. (정확하게는 HandlerMethodArgumentResolver 클래스에서 Argument들을 관리하는 역할을 한다.) 여기에 등록되어 있는, 자주 사용되는 파라미터 중 하나라고 할 수 있다. 주로 데이터를 관리하기 위한 파라미터이다. (MVC 패턴에서 M도 Model의 의미를 지니는 데, 그와 비슷하게 Model 객체도 Data를 전달하고 관리하기 위한 Argument 이다.)
Model과 ModelMap 두 객체는 기본적으로 상당히 비슷한 기능을 제공한다.
addAttribute(...) 메소드를 사용해서 다루고 싶은 데이터를 넣고,
getAttribute(...) 메소드를 이용해서 넣었던 데이터들을 빼서 사용할 수 있다.
2. Model 객체는 interface 이다.
public interface Model {
Model addAttribute(String attributeName, @Nullable Object attributeValue);
...
@Nullable
Object getAttribute(String attributeName);
}
Model 객체는 인터페이스로 구현되어 있기 때문에 map 인터페이스 구현체로의 변경이 쉬워서 코드의 유연성이 높다는 특징이 있다. 예를들어 TreeMap 이나 HashMap 으로도 호출할 수 있다.
(참고로, 페이지 redirect 시에 RUL parameter 정보들을 쉽게 관리하게 해주는 RedirectAttributes 인터페이스도 Model 인터페이스를 상속받는다.)
3. ModelMap 객체는 Class 이다. (LinkedHashMap)
public class ModelMap extends LinkedHashMap<String, Object> {
public ModelMap addAttribute(String attributeName, @Nullable Object attributeValue) {
Assert.notNull(attributeName, "Model attribute name must not be null");
this.put(attributeName, attributeValue);
return this;
}
...
@Nullable
public Object getAttribute(String attributeName) {
return this.get(attributeName);
}
}
구체적인 클래스로 구현되어 있기 때문에, LinkedHashMap 을 상속받은 클래스로 사용이 가능하다.
LinkedHashMap 클래스의 경우 HashMap 클래스를 상속받고 있는데, 이 둘(LinkedHashMap 과 HashMap)의 차이점은 순서의 유무이다. HashMap의 경우 순서 고려 없이 Entry에 Node 데이터를 집어 넣지만, LinkedHashMap의 경우 before, After Entry를 지정하여 put 한 순서데로 데이터를 저장한다는 차이점이 있다.
4. HandlerMethodArgumentResolver에 Model객체는 어떻게 등록되어 있을까?
public class ModelMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
public ModelMethodProcessor() {
}
// parameter 타입 특정하기 (간소화함)
public boolean supportsParameter(MethodParameter parameter) {
return Model.class;
}
// parameter 로써 역할 작성하기
@Nullable
public Object resolveArgument(...) throws Exception {
...
}
// return 타입 특정하기 (간소화함)
public boolean supportsReturnType(MethodParameter returnType) {
return Model.class;
}
// return 값으로써 역할 작성하기
public void handleReturnValue(...) throws Exception {
...
}
}
Model.class 의 경우 ModelMethodProcessor 클래스로 구현되어 있다. (참고로 함께 상속되어 있는 HandlerMethodReturnValueHandler 는 파라미터가 아니라 반환할 때의 데이터를 관리하기 위한 핸들러이다.)
기본적으로 스프링은, 컨트롤러의 파라미터들을 가져올 때 HandlerMethodArgumentResolver 를 상속받은 클래스들을 탐색한다. 마찬가지로 컨트롤러의 반환값들을 가져올 때는 HandlerMethodReturnValueHandler 인터페이스를 상속받은 클래스들을 탐색한다.
여기에 등록이 되어있어야 스프링이 파라미터나 반환값으로 인식할 수 있는 것이다.
'Framework > Spring' 카테고리의 다른 글
@ReqeustBody 바인딩시 boolean타입의 변수명 앞에 is를 붙이면 안되는 이유 (0) | 2024.06.26 |
---|---|
Spring Security 란? (0) | 2024.05.12 |
[Spring(intellij)-React 연동] Gradle 프로젝트로 연동하기 (0) | 2022.06.01 |
[JAVA Spring] 스프링의 존재 이유 (0) | 2022.04.25 |
처음에 Spring CRUD 만들면서 실수한 것들(내가 만난 오류들) (0) | 2022.03.14 |