Deep Dive /Java Web /8

8. FrameworkServlet → DispatcherServlet: doDispatch()

FrameworkServlet의 상위 기본 처리가 끝나면, DispatcherServlet의 doDispatch()로 실제 Spring MVC 로직이 실행되는 단계를 오픈소스 코드 근거로 분석합니다.


이번 단계의 역할 — 템플릿 메서드 패턴으로 service() → processRequest() → doService() → doDispatch()

  1. FrameworkServlet.service()가 호출 (상위 클래스 기본 처리)
  2. FrameworkServlet.processRequest()에서 doService()를 호출 (템플릿 메서드 패턴)
  3. DispatcherServlet.doService()에서 doDispatch() 호출 (하위 클래스 구현)
  4. doDispatch()에서 핸들러 매핑, 인터셉터, 컨트롤러 호출 등 모든 MVC 로직 실행

핵심 코드 — processRequest()가 뼈대를 잡고 doService()가 doDispatch()를 부른다

1) FrameworkServlet.service() → processRequest()

// FrameworkServlet.java
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    processRequest(request, response);
}

protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    try {
        doService(request, response); // 템플릿 메서드: 하위 클래스에서 구현
    }
    finally {
        ...
    }
}

2) DispatcherServlet.doService() → doDispatch()

// DispatcherServlet.java
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    try {
        doDispatch(request, response); // 실제 MVC 로직 시작
    }
    finally {
        ...
    }
}

protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 1. 핸들러 매핑
            mappedHandler = getHandler(processedRequest);

            // 2. 핸들러 어댑터 획득
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // 3. 인터셉터 preHandle
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // 4. 컨트롤러 호출
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            // 5. 인터셉터 postHandle
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }

        // 6. 뷰 렌더링
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    finally {
        ...
    }
}

호출 흐름 다이어그램 — doDispatch()가 HandlerMapping·Interceptor·Controller를 차례로 부른다

sequenceDiagram participant FrameworkServlet participant DispatcherServlet participant HandlerMapping participant Interceptor as HandlerInterceptor participant Controller FrameworkServlet->>DispatcherServlet: doService() DispatcherServlet->>DispatcherServlet: doDispatch() DispatcherServlet->>HandlerMapping: getHandler() HandlerMapping-->>DispatcherServlet: HandlerExecutionChain DispatcherServlet->>Interceptor: preHandle() DispatcherServlet->>Controller: handle() Controller-->>DispatcherServlet: ModelAndView DispatcherServlet->>Interceptor: postHandle()

코드 해설 — FrameworkServlet은 공통 처리를, DispatcherServlet은 오케스트레이션을 맡는다

이 단계에서 Spring MVC의 실제 오케스트레이션이 시작됩니다. FrameworkServlet은 템플릿 메서드 구조로 공통 요청 처리를 담당하고, DispatcherServlet.doDispatch()가 핸들러 조회·인터셉터·컨트롤러 호출·응답 렌더링까지 이어지는 전체 흐름을 주도합니다.


설계 의도 — FrameworkServlet이 뼈대를 잡고 DispatcherServlet이 doDispatch를 채운다

  • 템플릿 메서드 패턴: FrameworkServlet은 기본 구조(service → processRequest)를 정하고, DispatcherServlet에서 구체적 구현(doService → doDispatch)을 채움
  • 계층 분리: 상위 클래스에서 공통 처리(요청/응답 관리, 트랜잭션 처리)를 하고, 하위 클래스에서 MVC 로직(핸들러 매핑, 컨트롤러 호출)에 집중
  • 확장성: 다른 서블릿도 FrameworkServlet을 상속받아 자신의 doService()를 구현 가능

← 이전: 7. StandardWrapperValve → FrameworkServlet | 다음: 9. DispatcherServlet → HandlerMapping