서블릿 (Servlet)
- 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 애플리케이션 프로그래밍 기술
- 웹 요청과 응답의 흐름을 간단한 메서드 호출만으로 체계적으로 다룰 수 있게 지원
- HTTP 요청을 통해 매핑된 URL이 호출되면 service() 메서드를 실행
- HTTP 요청, 응답 메시지를 편리하게 사용할 수 있도록 도와주는 HttpServletRequest, HttpServletResponse 객체
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
...
}
}
HTTP 통신 과정 변화
서버 TCP/IP 연결 대기, 소켓 연결HTTP 요청 메시지 파싱 (헤더부, 바디부 ..)→ Request 객체- 비즈니스 로직
HTTP 응답 메시지 생성→ Response 객체TCP/IP 응답 전달, 소켓 종료
MVC 패턴
- 비즈니스 로직과 뷰 렌더링을 한번에 처리 -> 너무 많은 역할
- 비즈니스 로직을 수정하는 일과 UI를 수정하는 일은 각각 다르게 발생할 경우가 많고 대부분 서로에게 영향을 주지 않음
- MVC 패턴은 Controller와 View 영역으로 서로 역할을 나눈 것
- Controller : HTTP 요청을 받아서 파라미터 검증, 비즈니스 로직(Service 계층), View에 전달할 데이터를 Model에 저장
- Model : View에 전달할 데이터를 저장
- View : Model에 담겨있는 데이터를 사용해서 화면을 렌더링하는데 집중
Servlet + 기본 MVC 패턴의 문제점
- View로 이동하는 dispatcher.forward(request, response) 코드 중복 호출
- 모든 컨트롤러에 Servlet 선언 (종속성)
- 공통 처리가 어려움 -> 컨트롤러 호출 전에 공통 기능을 처리해줄 무언가 필요 (프론트 컨트롤러)
프론트 컨트롤러
- 스프링 MVC의 DispatcherServlet 역할
- 하나의 서블릿으로 사용 (공통 처리)
- URL 요청을 전부 이곳에서 받아 요청에 맞는 컨트롤러를 호출 -> 서블릿 종속성 제거
- 각각의 컨트롤러에서 View 네임을 반환하면 프론트 컨트롤러에서 경로(viewPath)를 생성 -> 코드 중복 제거
- 프론트 컨트롤러에서만 서블릿 선언을 해서 나머지 컨트롤러에서 서블릿 종속성 제거
- 모든 컨트롤러에서 Model을 반환하지 않도록 프론트 컨트롤러에서 따로 Model 객체를 생성해서 전달
- 여러 컨트롤러를 처리할 수 있도록 핸들러 어댑터 생성
@WebServlet(name = "FrontControllerSerlvetV5", urlPatterns = "/front-controller/v/*")
public class FrontControllerSerlvetV5 extends HttpServlet {
private final Map<String, Object> handlerMappingMap = new HashMap<>();
private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();
// 핸들러 매핑 등록, 핸들러 어댑터 등록
public FrontControllerSerlvetV5() {
initHandlerMappingMap();
initHandlerAdapters();
}
// 핸들러(컨트롤러) 초기화
private void initHandlerMappingMap() {
//v3 버전 컨트롤러
handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
//v4 버전 컨트롤러
handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
handlerMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
}
// 어댑터 초기화
private void initHandlerAdapters() {
handlerAdapters.add(new ControllerV3HandlerAdapter());
handlerAdapters.add(new ControllerV4HandlerAdapter());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 핸들러 조회
Object handler = getHandler(request);
// 요청 URL에 맞는 핸들러 객체가 없으면 종료
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 3. 핸들러에 맞는 핸들러 어댑터 조회
MyHandlerAdapter adapter = getHandlerAdapter(handler);
// 5. 핸들러 어댑터에 전달
// 어댑터는 request 파라미터를 Map 객체에 담고 model 객체를 따로 생성해서 전달
// 핸들러는 Servlet 종속성이 제거되고 ViewName만 반환하면 됨
ModelView mv = adapter.handle(request, response, handler);
// 6. ViewName(논리 이름)으로 View Resolver(풀 경로 생성) 실행
String viewName = mv.getViewName();
MyView view = viewResolver(viewName);
// 7. View 렌더링
view.render(mv.getModel(), request, response);
}
// 2. 요청 URL에 맞는 핸들러 객체를 handlerMappingMap에서 조회, 핸들러 객체 반환
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return handlerMappingMap.get(requestURI);
}
// 4. 해당 핸들러를 지원하는 핸들러 어댑터가 있는지 확인
private MyHandlerAdapter getHandlerAdapter(Object handler) {
for (MyHandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
throw new IllegalArgumentException("Error");
}
//ViewPass생성
private MyView viewResolver(String viewName) {
return new MyView("/WEB-INF/views/" + viewName + ".jsp");
}
}
[참고]인프런 김영한님 강의를 공부한 내용입니다.
'Spring' 카테고리의 다른 글
[스프링 MVC2] 메시지, 국제화 (0) | 2022.06.15 |
---|---|
[스프링 MVC2] 타임리프(Thymeleaf) 기본 문법 (0) | 2022.06.14 |
[스프링 MVC1] 서블릿, MVC 패턴 (2/2) (0) | 2022.06.13 |
[Spring] 스프링 핵심 개념 (2/2) (0) | 2022.06.13 |
[Spring] 스프링 핵심 개념 (1/2) (0) | 2022.06.10 |