Spring MVC는 Spring에서 제공하는 웹 모듈로, Model, View, Controller 세가지 구성요소를 사용해 사용자의 다양한 HTTP Request을 처리하고 단순한 텍스트 형식의 응답부터 REST 형식의 응답은 물론 View를 표시하는 html을 return하는 응답까지 다양한 응답을 할 수 있도록 하는 Java 프레임워크 입니다.
Spring MVC는 다양한 요청을 처리하고 응답하기 위해, 주요 구성요소들을 만들어놓고 구성요소들을 확장할 수 있게 만들어 놓습니다. 이들을 제대로 사용하기 위해서는 MVC가 어떻게 구성되어 있는지를 알아야 합니다. 아래 그림은 Spring MVC 라이프 사이클을 보여줍니다.
Spring MVC 요청 흐름과 라이프사이클
Filter -> DispatcherServlet -> HandlerMapping -> HandlerInterceptor -> controller -> Service -> Repository -> ViewResolver
위와 같은 순서로 요청이 들어오고 응답이 나갑니다. 각 단계별 처리 방식과 뜻을 알면 비즈니스 로직을 넣어야 할 곳을 알게되고, 코드를 작성할 때 도움이 됩니다. 기능 별로 어디에 코드를 작성해야 하는지 알게 되면 디버깅 및 유지보수에 큰 도움이 됩니다.
Filter
Filter는 Web Application의 전역적인 로직을 담당합니다.
Interceptor와 많이 비교되며, 가장 큰 특징은 모든 요청이 처음 도달하는 곳이라는 점입니다.
Filter라는 단어에서 알 수 있듯, Filter는 전체적인 필터링 설정을 하는 곳입니다.
DispatcherServlet에 들어가기 전인 Web Application 단에서 실행됩니다.
또한 Filter는 요청 내용을 변경하거나 체크하는 것을 수행하며, 자원의 처리가 끝난 후에도 응답 내용에 대해서 변경 처리가 가능합니다.
그래서 인코딩 변환 처리, XSS 방어 요청에 대한 처리도 Filter에서 처리합니다.
DispatcherServlet
Filter를 거쳐 처음 만나는 서블릿입니다. 모든 Request를 우선적으로 받아 처리해줍니다.
HandlerMapping에게 Request에 대해 매핑할 Controller 검색을 요청합니다.
HandlerMapping에서 Controller 정보를 반환받아 해당 Controller와 매핑합니다.
Dispatcher는 배치 담당자라는 뜻이 있습니다. 단어 뜻대로 Request에 대해 어느 Controller에 매핑 시킬 것인지 배치하는 역할을 합니다.
Servlet이란 Web에 대한 트래픽이 많아짐에 따라 Web Server 혼자서 처리했던 것을 Web Application Server를 추가하여 처리하게 되었습니다. 이것을 우리는 Servlet Container라고도 합니다. 이 WAS(Web Application Server)는 Web Server에 의해 전달된 요청을 처리하는데요. WAS에 의해서 관리 및 실행되는 것이 Servlet입니다. Servlet은 요청을 처리하는 것이라고 생각하면 되겠습니다.
Servlet Container는 WAS의 메인 기능이라고 할 수 있습니다.
https://thisisprogrammingworld.tistory.com/173
- 서블릿 클래스의 가져오기, 초기화, 호출, 소멸까지의 라이프 사이클을 관리하는 역할을 합니다.
- 웹 서버와 통신하여 동적 서비스를 응답하는데, 해당 통신을 위해 소켓을 만드는 역할을합니다.
- 요청을 받을 때마다 스레드를 생성해 요청을 처리하는 역할을 합니다. 여기서 서블릿 컨테이너에서 스레드 풀로 스레드를 별도로 관리하여 실행합니다.
HandlerMapping
HandlerMapping은 DispatcherServlet으로부터 검색 요청받은 Controller를 찾아 정보를 리턴하는 역할만 합니다.
HandlerInterceptor
HandlerIntercepter는 Request가 Controller에 매핑되기 전 앞단에서 부가적인 로직을 추가할 수 있습니다.
Filter에서는 전반적인 필터를 걸고 Interceptor에서는 Contorller로 들어가기 전 처리해야 할 작업을 미리 해주는 기능을 실행합니다.
주로 세션, 쿠키, 권한 인증, 로깅 등 공통 로직에 많이 사용됩니다.
Controller
Request와 매핑되는 곳입니다.
Request에 대해 어떤 로직으로 처리할 것인지를 결정하고, 그에 맞는 Service를 호출합니다.
Controller는 Service를 Bean으로 스프링 컨테이너로부터 제공 받습니다.
이를 통해 Service에 구현된 로직에 요청 값을 정리하여 전달합니다.
Service
Service는 데이터 처리 및 가공을 위한 비즈니스 로직을 수행합니다.
Request에 대한 실질적인 로직을 수행하기 때문에, Spring MVC Lifecycle에서 가장 중요하다고 할 수 있습니다.
Service에서 가장 중요한 비즈니스 로직을 처리하며, 요청에 대한 처리를 책임집니다.
Controller과 마찬가지로 Repository를 Bean으로 스프링 컨테이너로부터 제공 받습니다.
Repository에 데이터를 요청해 CRUD(Create, Read, Update, Delete)를 처리합니다.
Repositoy (DAO)
Repository는 데이터베이스에 접근하는 객체입니다. 줄여서 DAO(Data Access Object) 라고 합니다.
Service에서 데이터베이스에 접근할 수 있게 하여 데이터의 CRUD 및 다양한 Query를 실행합니다.
대부분 Database 연결에 활용되며, Repository만이 데이터에 접근할 수 있습니다.
ViewResolver
MVC 패턴에서 V는 View를 의미합니다. ViewResolver는 View를 랜더링 합니다.
Controller에서 리턴한 View의 이름을 DispatcherServlet으로부터 넘겨받고, 해당 View를 랜더링 합니다.
생성한 View를 DispatcherServlet으로 반환하고, DispatcherServlet에서는 전달 받은 View를 Response로 전달할 수 있도록 합니다.
RestController vs Controller
Controller를 구현하면 어노테이션으로 @RestController나 @Controller를 사용하게 됩니다.
여기서 @RestController와 @Controller의 차이점이 무엇일까요?
@RestController는 @Controller에 @ResponseBody가 추가된 형태입니다.
RestAPI를 개발할 때 많이 활용하며 대부분 Json 형태로 객체 데이터를 전달할 때 많이 활용합니다.
@RestController는 반환 시 ResponseEntity로 감싸서 반환합니다.
동작 과정도 기존 @Controller와 동일합니다.