♪ 학습 내용
더 실용적이고 유연한 컨트롤러 개선 (model을 파라미터로 / 어댑터 패턴 적용)
* model을 파라미터로
앞에서는 컨트롤러에서 ModelView 객체 생성하고 다시 반환해야했다.
어떻게 보면 귀찮은 작업..!
그래서 컨트롤러는 ModelView가 아닌 ViewName만을 반환하게끔 개선했다.
그렇다면 model은 어떻게 처리하지 ? 싶었지만
Map으로 구현한 model을 프론트 컨트롤러에서 컨트롤러를 호출할 때 파라미터로 넘겨주었다.
즉, 컨트롤러 입장에서는 파라미터로 넘어온 Map(model)에 데이터만 넣고, 반환은 뷰 이름만 반환하면 된다.
위의 프론트 컨트롤러에서 model 객체 (Map)를 생성하여 컨트롤러에게 파라미터로 넘기는 것을 확인 !
그리고 논리 이름인 ViewName이 반환되면 기존처럼 뷰 리졸버를 통해 물리 이름으로 변경 후 MyView 객체를 반환받고
render 해주면 끝.
render 할 때는 아까 생성한 model을 같이 넘겨주면 된다. ( 컨트롤러에서 model 객체에 데이터를 담았으니 )
view.render(model, request, response);
이렇게 해서 컨트롤러에서는 모델을 직접 생성할 필요 없이 뷰 이름만 반환하게끔 코드를 작성했다.
---> 개발자 입장에서는 매우 편리하고 깔끔해졌다.
* 어댑터 패턴
앞에서 개발해온 MVC 패턴은 다 좋은데, 한가지 방식의 인터페이스만 사용가능하다는 한계..
ex) ControllerV3 와 ControllerV4 호환이 불가
만약 다른 방식으로도 개발하고 싶으면?
두개가 안맞아서 중간에 뭐하나 끼워서 두개를 맞추는 것. 어댑터이다.
like) 일본여행 시 돼지코 어댑터
MVC 패턴에도 어댑터를 적용하여 여러 방식의 컨트롤러 처리할 수 있게끔!
전체적인 건 다음과 같다.
핸들러 어댑터가 바로 중간 어댑터 역할을 한다.
여기서 핸들러는 쉽게 생각하면 바로 컨트롤러이다.
근데 어댑터를 만듬으로써 컨트롤러 뿐만 아니라 다른 종류의 것도 처리할 수 있기 때문에(어댑터를 통해)
더 큰 범주에서 핸들러라고 변경한 것이다.
* 어댑터 패턴 도입
핸들러 어댑터는 프론트 컨트롤러와 핸들러 사이를 연결해주는 역할.
supports 메서드는 넘어온 handler 가 해당 어댑터와 호환하는 지 체크한다.
프론트 컨트롤러에서 handle 메서드를 호출하면 어댑터에서는 handler의 process를 호출, 모델뷰 반환!
즉, 징검다리 역할 또는 돼지코 역할
public boolean supports(Object handler){
return (handler instanceof ControllerV3);
}
V3용 핸들러 어댑터이므로 파라미터로 넘어온 핸들러가 ControllerV3의 인스턴스인지 확인하는 것을 확인.
public ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
ControllerV3 controller = (ControllerV3) handler;
Map<String, String> paramMap = createParamMap(request);
ModelView modelView = controller.process(paramMap);
return modelView;
}
handle 에서는 넘어온 Object 타입 handler를 ControllerV3 타입으로 캐스팅 !
이렇게 해도 되는건가 싶겠지만 이미 supports 메서드를 통해 handler 가 ControllerV3의 인스턴스라는 것을
체크하고 그에 맞는 본 핸들러 어댑터로 넘어온 것이기 때문에 캐스팅해도 문제 될 것이 없다.
controller.process(paramMap) 으로 컨트롤러 실행하고 반환된 ModelView를 반환 !
이전 프론트 컨트롤러와 비교하자면 이름이 변경된 것도 있고,
핸들러 어댑터를 저장하는 Map인 handlerAdapters 를 새로 만들었다.
private MyHandlerAdapter getHandlerAdapter(Object handler) {
for (MyHandlerAdapter adapter : handlerAdapters) {
if (adapter.support(handler)) {
return adapter;
}
}
throw new IllegalArgumentException("handler adapter를 찾을 수 없습니다. handler =" + handler);
}
handlerAdapters 에 저장되어있는 어댑터 중 파라미터로 넘어온 handler 와 호환 되는 어댑터를 찾아 반환한다.
위에서 살펴본 adapter의 support 메서드를 통해 호환이 가능한지 확인 !
service{
ModelView mv = adapter.handle(request, response, handler);
}
호환이 가능한 adapter 를 호출 ! adapter는 파라미터로 넘어온 handler( 여기서는 컨트롤러 ) 를 호출 !
프론트 컨트롤러는 이 과정에서 무조건 ModelView를 반환받도록 설계.
V3버전 또는 V4 버전의 컨트롤러는 반환하는 타입이 다르니까 중간에 어댑터를 통해 ModelView로 반환하게끔 하는거다.
추가로 컨트롤러를 호출할 때 넘겨야할 파라미터도 다르기 때문에 .
즉, Adapter는 핸들러에 맞는 형식으로 핸들러를 호출하고,
반환된 것을 어떻게든 ModelView로 바꾸어 프론트 컨트롤러에 반환하는 역할이다.
String viewName = controller.process(paramMap,model);
ModelView mv = new ModelView(viewName);
...
reutrn mv;
여기서 알 수 있듯이 V4컨트롤러는 파라미터로 넘겨야하는 것도, 반환되는 것도 V3와 다르다.
V4는 String을 반환하지만 어댑터는 ModelView를 반환해야하므로 직접 생성 후 형식에 맞추어 반환.
그렇기 때문에 해당 어댑터를 통해 호환되게끔 중간 다리 역할을 하고 있는 것이다 !!
V5의 프론트 컨트롤러를 통해 V3, V4 다 호환하는 모습을 확인 가능.
다형성과 어댑터를 이용해 기본 구조를 유지하며 MVC 프레임 워크 기능을 확장해보았다.
여기가지 해서 만든 프레임워크는 스프링 MVC와 매우 유사한 구조를 지니고 있다.
♪ 다음 학습 내용
스프링 MVC의 구조
'Dev > Spring' 카테고리의 다른 글
[Spring MVC 1] 스프링 MVC-구조 (2) (0) | 2023.01.31 |
---|---|
[Spring MVC 1] 스프링 MVC-구조 (1) (0) | 2023.01.30 |
[Spring MVC 1] MVC 프레임워크 만들기 (2) (0) | 2023.01.27 |
[Spring MVC 1] MVC 프레임워크 만들기 (1) (0) | 2023.01.25 |
[Spring MVC 1] 서블릿/JSP/MVC (2) (0) | 2023.01.24 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!