Spring MVC
이름에서 알 수 있듯이 Spring MVC
웹 계층 기술은 MVC
아키텍처를 기반으로 동작한다.
MVC는 프레젠테이션 계층의 구성요소를 정보를 담은 모델 (M) , 화면 출력 로직을 담은 뷰 (V) , 그리고 제어 로직을 담은 컨트롤러 (C) 로 분리하고 이 세 가지 요소가 서로 협력해서 하나의 웹 요청을 처리하고 응답을 만들어내는 구조다. (토비의 스프링 Vol.2 - 스프링 웹 기술과 스프링 MVC)
일반적으로 MVC 아키텍처는 프론트 컨트롤러(Front controller)
패턴과 함께 사용 되는데, Spring MVC
에서는 DispatcherServlet
이 프론트 컨틀롤러
역할을 한다.
Front Controller
그리고 DispatcherServlet
각 이름의 뜻에서도 쉽게 유추 할 수 있듯이, DispatcherServlet
은 클라이언트의 요청을 먼저 (앞에서) 받아서 공통 작업 등을 처리 한 뒤 해당 요청에 맞는 적절한 컨트롤러를 찾아 요청을 위임한다. 이 때 각 요청에 따라 적절한 컨트롤러를 찾아 매핑시키는 과정은 서블릿 컨테이너가 URL
매핑을 통해 요청을 처리할 서블릿의 service()
메소드를 호출하는 것과 유사한 과정으로 볼 수 있다.
MVC + DispatcherServlet
조합을 통해 HTTP 요청을 처리하는 과정을 보다 자세히 알아보자.
① HTTP 요청 (DispatcherServlet에서 HTTP 요청 확인)
② DispatcherServlet에서 컨트롤러로 HTTP 요청 위임
③ 컨트롤러 - 모델 생성 및 모델 (Map)에 값 저장
④ 생성한 모델과 사용할 뷰 정보 전달
⑤ DispatcherServlet 뷰 생성 요청
⑥ 뷰 작업을 통해 응답 데이터 생성 (이 때 뷰 오브젝트에서 생성한 모델 객체 참조)
⑦ HTTP 응답 (서블릿 컨테이너가 서블릿이 생성한 응답 값을 클라이언트에 전송)
Spring MVC
가 동작하는 원리를 이해하기 위해서는 위 세부 과정을 이해하는 것이 중요하다. 그런데 위 과정을 이해하는데 있어서 [ 그림 2 ] 의 HTTP 요청 처리 프로세스의 배경에 대해서 생각해볼 필요가 있다.
앞서 언급한 것 처럼 DispatcherServlet
을 중심으로 진행된다. 마치 DispatcherServlet
가 지휘자 처럼 각 상황마다 적절한 악기들을 조합해 연주를 이끌어가는 것 처럼 보인다. 지휘자는 오케스트라 (악단)에 구성된 악기, 연주자 등 모든 정보를 알고 있어야 하는 것처럼 DispatcherServlet
도 마찬가지로 실제 클라이언트 요청을 처리를 담당하는 컨트롤러에는 누가 있고, 어디에 저장되어 있는 지를 알고 있어야 한다.
② 번 에서 DispatcherServlet
로 부터 위임된 클라이언트 요청을 처리할 컨트롤러들은 어디에 저장되어 있을까?
How Spring MVC works [1] 에서 Spring Application + 웹 환경
에서 스프링 컨테이너가 어떻게 구성되는 지를 다뤘다. 아직 읽지 않은 분은 한 번 읽고 다시 이 지점으로 돌아와서 이어 읽기를 추천한다.
[ 그림 3 ] 에서 위 질문에 대한 답을 찾을 수 있는데, DispatcherServlet
이 Servlet WebApplicationContext
을 포함하고 있는 것을 볼 수 있다.
Spring
에서 제공한 DispatcherServlet
이 서블릿 컨테이너에 의해 초기화 될 때 서블릿 레벨의 Servlet WebApplicationContext
를 생성하고, DispatcherServlet
의 Servlet WebApplicationContext
에 대한 디폴트 설정을 기준으로 컨텍스트를 구성한다.
디폴트 설정을 기준으로 여러 웹 프레젠테이션 계층의 컴포넌트들이 이 곳에 저장되고, 그리고 위에서 질문 했던 컨트롤러
역시 이 곳에 위치한 것을 확인 할 수 있다.
참고로 Servlet Series[2]- How the Servlet Container Handles a request 에서 언급한 것 처럼 서블릿 컨테이너가 서블릿 초기화 방식을 load-on-startup
설정 값을 통해 조정할 수 있다고 했다. Servlet WebApplicationContext
가 DispatcherServlet
이 초기화 되는 시점에 생성되기 때문에 이 설정 값에 따른 차이를 꼭 알아보길 바란다.
DispatcherServlet
가 Servlet WebApplicationContext
을 통해서 웹 계층 컴포넌트를 사용할 수 있기 때문에 [ 그림 2 ] 프로세스의 핵심 엔진 역할을 할 수 있다. 하지만 [ 그림 2 ] ③ 번 과정에서 각 컨트롤러가 동적인 모델 객체를 생성하기 위해서는 이를 처리할 서비스 계층, 데이터 액세스 계층에도 접근할 수 있어야 한다.
결론부터 말하면, [ 그림 3 ] 에서 볼 수 있듯이 Root WebApplicationContext
방향으로 의존 관계를 가져야 한다. (서비스, 데이터 액세스 계층 컴포넌트가 이 곳에 저장되어 있으므로) Spring MVC
에서는 두 컨텍스트의 의존 관계를 구성하기 위해서 컨텍스트 계층구조를 활용해서 자식 컨텍스트인 Servlet WebApplicationContext
에서 부모 컨텍스트로의 접근이 가능하도록 했다.
Spring MVC
에서 DispatcherServlet
을 중심으로 HTTP 요청을 처리하는 과정과 그 처리 과정이 가능한 배경에 대해서 알아봤다. How Spring MVC works
3부에서는 [ 그림 2 ] 에서 ② 과정을 보다 자세히 다뤄 볼 예정이다.
토비의 스프링 Vol. 1 | 1.4 제어의 역전 (IoC)
토비의 스프링 Vol. 2 | 1.5 스프링의 IoC
토비의 스프링 Vol. 2 | 1.1 IoC 컨테이너: 빈 팩토리와 애플리케이션 컨텍스트
토비의 스프링 Vol. 2 | 3.1 스프링의 웹 프레젠테이션 계층 기술
Web on Servlet Stack
Tomcat, Spring MVC의 동작 과정