본문 바로가기

SPRING

[Spring MVC] 스프링 MVC 아키텍쳐

Dispstchater Servlet의 요청 처리 과정

1. 일단 Dispatcher Servlet은 프론트 컨트롤러이다. 즉, 우리가 이클립스 STS 환경에서 Spring MVC 프로젝트를 생성했을때 생기는 app-servlet.xml 파일 정도가 되겠다. 최초의 스프링 환경설정에 대한 내용들이 포함되는 파일이기도 하다. 

2. 간단하게 요청-위임-렌더링위임-결과 정도로 쉽게 순서를 보면 된다.

3. 하나 이상의 구현체를 가지고 있다.


스프링 MVC는 모두 이 프론트 컨트롤러 위주로 동작하게 되어 있으며 핸들러를 위임하는 일과 View 템플릿에게 렌더링을 위임하는 것도 모두 이 Dispatcher Servlet의 역할이다.


크게 처리 결과는 다음과 같다.

1. Client로 부터 요청

2. 요청 선처리 작업

3. 핸들러 결정

4. 핸들러 실행

5. 예외발생 여부에 따라 View 랜더링

6. 사용자 화면에 표출


저기 위에서 요청 선처리 작업이라는 부분은 다시 다음과 같은 것들을 처리하며 이러한 순서를 가진다.


Dispatcher Servlet은 요청 핸들러에 전달해서 처리하기 전에 요청에 대한 선처리 작업을 진행한다. 우선 org.springframework.web.servlet.LocaleResoler를 이용해서 현재의 요청에 해당하는 java.util.Locale을 결정하고 노출한다. 그런 후 ㅕㄴ재의 요청을 org.springframework.web.context.requestRequestcontextHolder에 저장하고 노출한다.

이유는 처리 단계마다 필요한 해당 정보를 가져오는 것이 아니라 모든 정보를 넘겨받지 않고 손쉽게 정보를 얻기 위함이다.

일단 선처리에서는 HTTP 요청인지 아닌지를 판가름하고 요청 타입이 멀티파트이면 org.springframework.web.multipart.MultipartResolver가 해당 요청을 org.springframework.web.multipart.multipartHttpServletRequest로 감싸게 된다.


즉 다음과 같은 순서를 가진다.


1. 요청

2, Locale 결정

3. RequestContextHolder에 저장

4. FlashMap 복원

5. 멀티파트 요청 ?

6. 핸들러 결정과 실행


HandlerExecutionChain 결정

DispatcherServlet은 요청을 전달할 준비가 되면 한개 이상의 org.springframework.web.servlet.HandlerMapping 구현체에 문의해 어떤 핸들러가 요청을 처리할 것인지 결정한다(어떠한 Controller) 핸들러가 결정되면 실제로 그 핸들러를 실행하기 위해 org.springframework.web.servlet.HandlerAdapter를 찾게 된다.

만약 이를 못찾게 된다면 java.servlet.ServletException이 발생한다.


1. 요청

2. HadnlerMapping으로 HandlerExecutionChain결정

3. HandlerExecutionChain 발견

4. HandlerAdapter 결정

5. HandlerAdapter 발견

6. 요청 처리

중간 중간 HandlerExecutionChain을 발견 못하거나 HandlerAdapter를 발견 못하면 각각 Exception을 발생하게 된다.


HandlerExecutionChain 실행

DispatcherServlet은 무엇을 실행하는지 알고 있는 HandlerExecutionChain을 통해 요청을 처리한다. 필요한 경우 설정된 Intercepter를 통해서 preHandle과 postHandle이 구현체를 참고한다. 이 intercepter는 횡단 관심사를 적용하는데 필요하다. 요청이 처리되면 다시 intercepter의 postHandle을 실행하고 요청을 마친다.

1. 결정된 HandlerExecutionChain

2. 사용가능한 인터셉터 존재하는가 ?

3. 핸들러 실행

4. ModelAndView 리턴

5. ModelAndView가 view를 갖는가 ?

6. 인터셉터의 postHandle을 호출해서 후처리기 요청 처리

7. view 렌더링 

여기서 6번 항목의 view를 갖지 못하다면 RequestToViewNameTranslator를 사용하여 View를 찾게 되어있다. 이것은 다양한 방법이 있는데 좀 이따가 아래서 보자.


예외처리

요청을 처리하는 동안 예외가 발생하면 DispatcherSevlet은 org.springframework.web.servlet.HandlerExceptionResolver에게 어떻게 예외를 처리할 것인지 물어본다.

1. 요청 처리시 에러 발생

2. HandlerExceptionResolver에게 문의

3. ModelAndView 리턴?


View 렌더링

요청 처리과정동안 View가 결정되면 DispatcherServlet은 우선 이 View가 java.lang.String을 참조하는지 체크한다. 만약 참조한다면 org.springframework.web.servlet.ViewResolver에게 실제 org.springframework.web.servlet.View 구현체를 갖고오게 요청한다. 물론 찾을 수 없으면 javax.servlet.servletException을 던지게 된다.


1. 뷰 렌더링

2, 뷰가 String을 참조 ?

3. 뷰 구현체가 존재 ?

4. 뷰 구현체로 렌더링

5. 요청처리 재개


요청 처리 종료

각 요청은 무조건 요청 처리 종료를 거친다. HandlerExecutionChain이 있으면 afterCompletion 메소드를 호출한다. 단, preHandle 메소드를 성공적으로 호출한 인터셉터만이 afterCompletion 메소드르 호출할 자격을 얻는다.