현재는 어떤 컨트롤러 interface를 사용할 것인지 지정되어 있기 때문에 컨트롤러에 따라 다른 interface를 사용하는 것이 불가능하다.
만약 각각의 컨트롤러에 따라 다른 interface를 사용하고 싶다면 이때 사용하는 것이 어댑터이다.
어댑터 패턴을 사용하여 프론트 컨트롤러가 다양한 방식의 컨트롤러 interface를 처리하도록 해보자.
- 핸들러 어댑터 : 중간에서 다양한 종류의 컨트롤러를 호출할 수 있는 어댑터 역할
- 핸들러 : 컨트롤러에 국한된 개념이 아니라 어떤 것이든 해당하는 종류의 어댑터만 있다면 다 처리 가능
어댑터 Interface
- supports : 어댑터 목록을 조회하여 해당 컨트롤러를 처리할 수 있는지 판단하는 메서드
- True / False 값 반환
- handle : 실제 컨트롤러를 호출, ModelView 타입으로 반환
ControllerV3 어댑터
- supports를 통해 parameter로 넘어온 handler가 ControllerV3의 객체 인스턴스라면 True, 그렇지 않으면 False를 반환시켜 준다.
- ControllerV3는 애초에 ModelView를 반환하도록 설계되어있기 때문에 그대로 반환시키기만 하면 된다.
- supports 메서드를 통해 ControllerV3의 인스턴스인지 걸러서 가져오기 때문에 캐스팅하여 사용 가능
FrontController
- 생성자를 통해 핸들러 매핑과 어댑터들을 초기화하는데 현재는 V3어댑터만 만들어놓은 상태
- 이전에는 매핑 정보의 값이 Map<String, ControllerV3>과 같이 지정되어 있었지만 현재는 Object로 어떤 인터페이스든 받을 수 있도록 하였다.
서비스 로직
- getHandler 메서드를 사용하여 handlerMappingMap에서 URL에 매핑된 핸들러 객체를 찾아 반환한다.
- handler를 처리할 수 있는 어댑터를 supports를 통해 찾는다. 만약 찾지 못할 경우 Exception 던짐
- handler가 ControllerV3의 인터페이스를 구현했다면 ControllerV3HandlerAdapter가 반환
- 어댑터의 handle 메서드를 통해 실제 어댑터가 호출되고, 그 결과를 ModelView로 반환
- 이를 viewResolver로 뷰에 담아 렌더링
ControllerV4 또한 사용할 수 있도록 추가해보자
- FrontControllerServletV4에서 하던 역할을 어댑터가 수행한다.
- ControllerV4는 process를 수행한 결과를 논리적인 주소(viewName)으로 반환하는데 이를 ModelView에 model과 함께 담아 ModelView형식으로 값을 반환시켜 준다.
코드를 살펴보면 ControllerV4를 위한 어댑터를 만들어 확장시킨 것이지 기존의 FrontControllerServletV5의 기본 로직은 그대로이다. 단지 handlerAdapters와 hanlderMappingMap에
V4관련 값만 추가해주었다. ==> OCP를 잘 지키고 있음
반응형
'Spring > Spring MVC' 카테고리의 다른 글
Handler Mapping & Handler Adapter (0) | 2021.04.30 |
---|---|
Spring MVC 전체 구조 (0) | 2021.04.30 |
단순하고 실용적인 컨트롤러 (0) | 2021.04.21 |
Model 추가 (0) | 2021.04.18 |
View 분리 (0) | 2021.04.14 |