본문 바로가기
JAVA Spring

유연한 컨트롤러1 v5, 유연한 컨트롤러2 v5

by ppirae 2022. 4. 5.

유연한 컨트롤러1 - v5

만약 어떤 개발자는 ControllerV3 방식으로 개발하고 싶고, 어떤 개발자는 ControllerV4 방식으로 개발하고 싶다면 어떻게 해야할까?

 

어댑터 패턴

지금까지 우리가 개발한 프론트 컨트롤러는 한가지 방식의 컨트롤러 인터페이스만 사용할 수 있다.

ControllerV3 , ControllerV4 는 완전히 다른 인터페이스이다. 따라서 호환이 불가능하다.

마치 v3는 110v이고, v4는 220v 전기 콘센트 같은 것이다. 이럴 때 사용하는 것이 바로 어댑터이다.

어댑터 패턴을 사용해서 프론트 컨트롤러가 다양한 방식의 컨트롤러를 처리할 수 있도록 변경해보자.

 

V5 구조

  • 핸들러 어댑터: 중간에 어댑터 역할을 하는 어댑터가 추가되었는데 이름이 핸들러 어댑터이다. 여기서 어댑터 역할을 해주는 덕분에 다양한 종류의 컨트롤러를 호출할 수 있다.
  • 핸들러: 컨트롤러의 이름을 더 넓은 범위인 핸들러로 변경했다. 그 이유는 이제 어댑터가 있기 때문에 꼭 컨트롤러의 개념 뿐만 아니라 어떠한 것이든 해당하는 종류의 어댑터만 있으면 다 처리할 수 있기 때문이다.

MyHandlerAdapter

  • boolean supports(Object handler)
    • handler는 컨트롤러를 말한다.
    • 어댑터가 해당 컨트롤러를 처리할 수 있는지 판단하는 메서드다.
  • ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
    • 어댑터는 실제 컨트롤러를 호출하고, 그 결과로 ModelView를 반환해야 한다.
    • 실제 컨트롤러가 ModelView를 반환하지 못하면, 어댑터가 ModelView를 직접 생성해서라도 반환해야 한다.
    • 이전에는 프론트 컨트롤러가 실제 컨트롤러를 호출했지만 이제는 이 어댑터를 통해서 실제 컨트롤러가 호출된다.

ControllerV3HandlerAdapter

public boolean supports(Object handler) {
 return (handler instanceof ControllerV3);
}

ControllerV3 을 처리할 수 있는 어댑터를 뜻한다.

ControllerV3 controller = (ControllerV3) handler;

Map<String, String> paramMap = createParamMap(request);
ModelView mv = controller.process(paramMap);

return mv;

handler를 컨트롤러 V3로 변환한 다음에 V3 형식에 맞도록 호출한다.

supports() 를 통해 ControllerV3 만 지원하기 때문에 타입 변환은 걱정없이 실행해도 된다.

ControllerV3는 ModelView를 반환하므로 그대로 ModelView를 반환하면 된다.

 

FrontControllerServletV5

컨트롤러(Controller) -> 핸들러(Handler)

 

생성자

 

매핑 정보

private final Map handlerMappingMap = new HashMap<>();

 

핸들러 매핑

private Object getHandler(HttpServletRequest request) {
    String requestURI = request.getRequestURI();
    return handlerMappingMap.get(requestURI);
}

 

핸들러를 처리할 수 있는 어댑터 조회

for (MyHandlerAdapter adapter : handlerAdapters) {
    if (adapter.supports(handler)) {
        return adapter;
    }
}

 

어댑터 호출

ModelView mv = adapter.handle(request, response, handler);


유연한 컨트롤러2 - v5

FrontControllerServletV5 에 ControllerV4 기능도 추가해보자.

핸들러 매핑( handlerMappingMap )에 ControllerV4 를 사용하는 컨트롤러를 추가하고, 해당 컨트롤러를 처리할 수 있는 어댑터인 ControllerV4HandlerAdapter 도 추가하자.

 

ControllerV4HandlerAdapter

public boolean supports(Object handler) {
 return (handler instanceof ControllerV4);
}

handler 가 ControllerV4 인 경우에만 처리하는 어댑터이다.

 

실행 로직

ControllerV4 controller = (ControllerV4) handler;
Map<String, String> paramMap = createParamMap(request);
Map<String, Object> model = new HashMap<>();
String viewName = controller.process(paramMap, model);

handler를 ControllerV4로 케스팅 하고, paramMap, model을 만들어서 해당 컨트롤러를 호출한다. 그리고 viewName을 반환 받는다.

 

어댑터 변환

ModelView mv = new ModelView(viewName);
mv.setModel(model);
return mv;

어댑터에서 이 부분이 단순하지만 중요한 부분이다.

어댑터가 호출하는 ControllerV4 는 뷰의 이름을 반환한다. 그런데 어댑터는 뷰의 이름이 아니라 ModelView 를 만들어서 반환해야 한다. 여기서 어댑터가 꼭 필요한 이유가 나온다.

ControllerV4 는 뷰의 이름을 반환했지만, 어댑터는 이것을 ModelView로 만들어서 형식을 맞추어 반환한다.

 

어댑터와 ControllerV4


정리

  • v1: 프론트 컨트롤러를 도입
    • 기존 구조를 최대한 유지하면서 프론트 컨트롤러를 도입
  • v2: View 분류
    • 단순 반복 되는 뷰 로직 분리
  • v3: Model 추가
    • 서블릿 종속성 제거
    • 뷰 이름 중복 제거
  • v4: 단순하고 실용적인 컨트롤러
    • v3와 거의 비슷
    • 구현 입장에서 ModelView를 직접 생성해서 반환하지 않도록 편리한 인터페이스 제공
  • v5: 유연한 컨트롤러
    • 어댑터 도입
    • 어댑터를 추가해서 프레임워크를 유연하고 확장성 있게 설계'

이제 스프링 MVC의 핵심 구조를 파악하는데 필요한 부분을 모두 만들었다.

다음에는 스프링 MVC를 학습해보자.


인프런 김영한님의 스프링 MVC 1편을 듣고 작성한 글입니다.

https://inf.run/V5Dz

 

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의

웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -

www.inflearn.com

 

댓글