티스토리 뷰

[ Spring Study ]
스프링에 대해 전반적인 구조 및 흐름에 대해서 몰랐던 부분이 너무나 많다는 걸 깨닫게 되는 순간..
한번 쯤 어디선가 읽어봤던 내용들에 대해 개념을 제대로 알고자 스프링에 대해 처음부터 공부한다.
경보 속도로 공부해보자 ! ! !

.

.

한번 쯤 DispatcherServlet 에 대해 들어 본 적이 있으며, 유명한 Spring Request 처리 방식에 대한 그림도 본 적이 있다.

하지만 여러 번 보고 듣는다 한들 전부 뇌리에 스쳐 지나갔다.

지금이라도 Spring 에서 사용자의 요청을 어떻게 처리하는지에 대해서 자세히 알아봐야 하지 않을까 ?

.

.

DispatcherServlet 은 spring 기반 웹 애플리케이션의 Front Controller 역할을 한다.

 

🤚 Front Controller 는 무엇이길래 ? Front Controller 부터 짚고 넘어가보자.

Front Controller 는 소프트웨어 디자인 패턴으로  웹 애플리케이션으로 요청이 들어오면 *서블릿 하나로 모든 요청을 받는다.

프론트 컨트롤러는 클라이언트의 요청을 받은 후, 해당 요청은 어느 컨트롤러가 처리해야 되는지를 결정한다.

프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 된다.

(* 프론트 컨트롤러를 사용하지 않았을 당시에는, 요청 별로 서블릿을 생성하였다.)

.

.

DispatcherServlet 으로 넘어와서..

DispatcherServlet 이 프론트 컨트롤러 역할을 할 수 있는 건, 프론트 컨트롤러 패턴으로 구현되어 있기 때문이다.

HTTP Request 를 처리하고 위임하고, 핸들러 · 컨트롤러 · 응답 객체로 구성된 스프링 애플리케이션 내에 구현된 HandlerAdapter 인터페이스에 설정에 따라 요청을 처리한다.

 

DispatcherServlet 이 동작하는 흐름을 확인해보자.

 

https://terasolunaorg.github.io/guideline/1.0.1.RELEASE/en/Overview/SpringMVCOverview.html

1) HTTP 요청 : DispatcherServlet 이 request 를 받는다.

 

2) 핸들러 조회 : DispatcherServlet 은 *HandlerMapping 을 통해 요청과 관련된 핸들러(Controller) 를 조회한다.

즉, 어떤 컨트롤러가 요청을 처리할 것인지를 결정한다.

 

3) 핸들러 어댑터 조회 : DispatcherServlet 은 *HandlerAdapter 를 통해 핸들러(Controller)를 실행할 수 있는 핸들러 어댑터를 조회한다.

 

4) 핸들러 어댑터 실행 : HandlerAdapter 는 핸들러(Controller) 를 호출한다.

즉, HandlerMapping 을 통해 찾은 핸들러를 직접 실행한다.

 

5) ModelAndView 반환 : 핸들러(Controller)는 비즈니스 로직을 처리한 후, Model 에 결과 값을 담고 HandlerAdapter 에게 view의 논리적인 이름을 반환한다.

 

6) ViewResolver 호출 : DispatcherServlet 은 *ViewResolver 를 호출하여 뷰의 논리 이름을 물리 이름으로 바꾸고, view 객체를 반환한다.

 

7) View 반환 : DispatcherServlet 은 view 에게 model을 전달하고 화면 표시(render)를 요청한다.

 

8) HTML 응답 : model 에 담아있던 데이터를 view 에 보여준다.

 

DispatcherServlet 핵심 로직 분석

protected void doDispatch(HttpServletRequest request, 
                              HttpServletResponse response) throws Exception {

    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    ModelAndView mv = null;

    // 핸들러 조회
    mappedHandler = getHandler(processedRequest);
    if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
    }
    // 핸들러 어댑터 조회 (핸들러를 처리할 수 있는 어댑터)
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
    // 핸들러 어댑터 실행
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

private void processDispatchResult(HttpServletRequest request,
                                   HttpServletResponse response, 
                                   HandlerExecutionChain mappedHandler, 
                                   ModelAndView mv, Exception exception) throws Exception {
    // 뷰 렌더링 호출
    render(mv, request, response);
}

protected void render(ModelAndView mv, HttpServletRequest request,
                      HttpServletResponse response) throws Exception {
    View view;
    String viewName = mv.getViewName();
    // 뷰 리졸버를 통해 뷰 찾기
    view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
    // 뷰 렌더링
    view.render(mv.getModelInternal(), request, response);
}

 

참고

스프링 MVC 1편  - 김영한

'Framework > Spring' 카테고리의 다른 글

auto-configuration에 대하여  (0) 2024.10.23
[Web] Servlet 과 Servlet Container  (0) 2022.12.26
[Spring] 순환 참조  (0) 2022.12.13
[JPA] N + 1 문제  (0) 2022.12.05
[JPA] 즉시로딩과 지연로딩  (0) 2022.11.14
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함