1. 디스패처 서블릿(Dispatcher Servlet)이란?
- 스프링 MVC 프레임워크의 중심축으로, 모든 웹 요청의 진입점 역할을 처리하는 중앙 컨트롤러. (중앙 집중)
- 모든 HTTP 요청을 가장 먼저 받아서 적절한 세부 컨트롤러에게 배분하는 역할을 한다.
- 내부적으로 핸들러 매핑을 통해 Spring IoC 컨테이너(Root Context, Servlet Context)와 연결되어 효율적으로 컴포넌트들(Spring Bean)을 제어.
- 요청을 받아서 적절한 컨트롤러(@Controller 또는 @RestController)에게 전달(Dispatch)하는 역할을 전담한다.
- 디자인 패턴 중 프론트 컨트롤러 패턴을 통해 구현함.
- HttpServlet을 상속받은 단 하나의 거대한 대표 서블릿
프론트 컨트롤러(Front Controller) 패턴
디스패처 서블릿은 디자인 패턴 중 프론트 컨트롤러 패턴을 통해 구현함.
- 디스패처 서블릿이 도입되면서 가장 앞단에서 모든 요청을 하나의 서블릿으로 일괄 수집하고, 공통 작업(인코딩, 보안, 로그 등)을 처리한 뒤 담당자에게 넘겨주는 방식으로 구조가 단순해짐.
- 담당자 = 해당 요청을 처리할 세부 컨트롤러
- 기존 Servlet 방식에는 모든 URL마다 각각의 서블릿을 만들어 관리해야 해서 중복 코드가 많고 관리가 힘듦.
- 요청을 받아서 적절한 컨트롤러(@Controller 또는 @RestController)에게 전달(Dispatch)하는 역할을 전담한다.
2. 레거시 방식의 핵심 동작 흐름 (Request Lifecycle)
Spring MVC의 전통적인(JSP/HTML) 방식에서는 디스패처 서블릿이 요청을 받으면 다음과 같은 순서로 작업을 지휘한다.
(일반 MVC(HTML/View 반환) 방식)
- 요청 접수: 클라이언트(브라우저)가 보낸 HTTP 요청을 디스패처 서블릿이 가장 먼저 받음.
- 컨트롤러 찾기 (Handler Mapping): 이 URL 요청은 어떤 컨트롤러가 처리해야 하는지 HandlerMapping에게 물어보고 담당 컨트롤러(Handler)를 찾는다.
- 컨트롤러 실행 (Handler Adapter): 찾은 컨트롤러를 직접 실행할 수 없으니, 중간 연결 고리인 HandlerAdapter를 거쳐서 컨트롤러의 메서드를 호출한다.
- 비즈니스 로직 수행: 개발자가 작성한 Controller ➔ Service ➔ Repository 구조를 타며 실제 데이터 처리가 이루어짐.
- 결과 반환 (ModelAndView): 컨트롤러가 로직 처리를 마치고 처리 결과 데이터(Model)와 화면 이름(ViewName)을 디스패처 서블릿에게 돌려줌.
- 뷰 찾기 (View Resolver): 디스패처 서블릿은 받은 화면 이름(예: "home")을 가지고 ViewResolver를 찾아가 이름에 맞는 실제 뷰 파일(JSP, Thymeleaf 등)을 찾아달라고 요청.
- 설정된 접두사/접미사(예: /WEB-INF/views/ + home + .jsp)를 결합하여 실제 파일 위치를 찾음.
- 응답 생성: 찾아낸 뷰/템플릿(JSP, Thymeleaf 등)에 모델 데이터를 채워 최종 HTML을 생성.
- 응답 반환: 완성된 HTML 화면을 브라우저(클라이언트)에 전달함.
3. REST API 환경에서의 디스패처 서블릿 흐름 (Request Lifecycle)
REST API 환경에서는 뷰(View)를 찾지 않고 데이터(여기선 JSON)를 직접 반환하므로, 전체 처리 흐름이 다음과 같이 진행된다. 위의 [6번, 7번 단계] 참고.
- 요청 접수: 위와 동일
- URL 매핑 조회 (HandlerMapping): 들어온 요청을 처리할 컨트롤러/메서드를 찾는다
- 컨트롤러 실행 (HandlerAdapter): @RestController가 붙은 메서드(컨트롤러)를 호출한다
- 비즈니스 로직 수행: 동일
- 자바 객체 반환: 결과로 자바 객체(예: UserDto, List<Post> 등)를 반환한다.
- 위의 [4번, 5번]에 대응
- 뷰 리졸버 건너뛰기(미호출): ViewResolver를 호출하지 않고 @ResponseBody를 감지한다. @ResponseBody(또는 @RestController)가 붙어 있으면 화면을 찾을 필요가 없다고 판단하기 때문.
- HttpMessageConverter 작동(직렬화): 대신 HttpMessageConverter를 거친다. 이 안의 MappingJackson2HttpMessageConverter 등이 작동하여 자바 객체를 JSON 문자열로 변환한다.
- 응답 반환: 변환된 JSON 데이터를 HTTP Response Body에 그대로 담아서 브라우저나 클라이언트(앱, React, Vue 등)에게 던져줌.
4. 기존의 MVC 방식과 REST API 차이점
1) 핵심 개념 비교
- 상황 예시: 디스패처 서블릿에게 'home' 화면 그려달라고 요청
- 기존 방식(레거시): ViewResolver가 home.html 찾아서 렌더링한다 (View(HTML) 응답)
- 각 URL마다 서블릿을 한 개씩 매핑하거나(서블릿을 각각 만들고 등록) web.xml을 꼼꼼히 설정해야 함.
- REST API 방식: 'home'에 대한 데이터(객체) 보내는 대신 알아서 가공해서 클라이언트으로 내보달라고 요청하는 것 ➔ HttpMessageConverter가 JSON/XML으로 바꿔서 그대로 반환
2) 두 방식의 전체 흐름 비교
| 레거시 방식 (HTML/View) | REST API 방식 (JSON/Data) | 차이점 및 핵심 포인트 | |
| 1 | 요청 접수 (DispatcherServlet이 요청 받음) |
요청 접수 (DispatcherServlet이 요청 받음) |
동일 (프론트 컨트롤러 역할) |
| 2 | 컨트롤러 찾기 (HandlerMapping) |
URL 매핑 조회 (HandlerMapping) |
동일 (@Controller vs @RestController 검색) |
| 3 | 컨트롤러 실행 (HandlerAdapter) |
컨트롤러 실행 (HandlerAdapter) |
동일 (HandlerAdapter를 거쳐 메서드 호출) |
| 4 | 비즈니스 로직 수행 | 비즈니스 로직 수행 | 동일 |
| 5 | ModelAndView 반환 | 자바 객체 반환 (DTO, List 등) |
레거시는 Model+ViewName 반환, REST API는 순수 데이터 객체 반환 |
| 6 | 뷰 찾기 (ViewResolver 호출) |
@ResponseBody 감지 & HttpMessageConverter 작동 (뷰 리졸버 건너뛰기) |
@ResponseBody로 인해 ViewResolver 완전 생략 ViewResolver 대신 Converter가 작동함 |
| 7 | 응답 생성 (HTML 렌더링) |
HttpMessageConverter 작동 (JSON 변환) |
HTML 템플릿 렌더링 vs Jackson을 통한 JSON 직렬화 |
| 8 | 최종 응답 반환 (HTML 전달) |
응답 반환 (Response Body에 JSON 전달) |
레거시는 7단계로 표현, REST API는 5~6을 하나로 묶어 6단계로 정리 가능 |
더보기
ℹ️ 차이점 비교 추가 설명
1) 공통점 (요청 처리의 기본 메커니즘)
- HandlerMapping (컨트롤러 조회): 요청 URL 및 HTTP 메서드를 기반으로 어떤 컨트롤러(Handler)가 요청을 처리해야 하는지 조회한다.
- HandlerAdapter (컨트롤러 실행): 찾은 컨트롤러를 실행시킬 수 있는 어댑터를 찾아 컨트롤러 메서드를 호출한다.
- 💡 왜 어댑터 패턴을 사용할까? 개발자가 작성하는 컨트롤러마다 반환 형태(String, ModelAndView, ResponseEntity 등)나 선언 방식이 제각각이기 때문에, 이를 일관된 방식으로 실행하기 위해 어댑터 패턴을 활용한다.
2) 차이점 (응답 방식에 따른 내부 동작)
- 뷰 리졸버 건너뛰기 (@ResponseBody / @RestController): @RestController는 내부적으로 @Controller + @ResponseBody 구조. @ResponseBody가 붙어 있으면 ReturnValueHandler가 ViewResolver를 호출하는 대신 HttpMessageConverter를 선택하도록 동작한다.
- HttpMessageConverter 및 MappingJackson2HttpMessageConverter (데이터 직렬화): 반환 객체가 자바 객체(DTO, List 등)이고 클라이언트 요청의 Accept 헤더가 JSON 형식일 경우, 기본 메시지 컨버터 중 Jackson 라이브러리를 사용하는 MappingJackson2HttpMessageConverter가 작동하여 자바 객체를 JSON으로 직렬화(Serialize)한다.
📊 핵심 차이점 비교 요약
| 기존 MVC (@Controller) | REST API (@RestController) | |
| 최종 반환 목적 | 클라이언트에게 보여줄 HTML 화면(View) | 클라이언트가 필요로 하는 데이터(JSON / XML) |
| 핵심 컴포넌트 | ViewResolver (뷰 리졸버) | HttpMessageConverter (메시지 컨버터) |
| 동작 방식 | 컨트롤러가 반환한 문자열(예: "home")을 바탕으로 실제 HTML/JSP 파일을 찾아서 렌더링함. | 자바 객체를 JSON 문자열로 변환하여 HTTP 응답 본문(Body)에 직접 집어넣음. |
5. 왜 사용할까? (디스패처 서블릿 & 프론트 컨트롤러의 장점)
① 공통 처리의 일원화 (중앙 집중 관리)
- 기존 문제점: 과거 Servlet 방식에서는 모든 URL 서블릿마다 인코딩 처리, 인증/인가, 로깅 등의 코드를 일일이 중복 작성해야 했음.
- 개선점: 모든 HTTP 요청이 디스패처 서블릿을 거치므로 보안, 인터셉터(Interceptor), 예외 처리(Global Exception Handler), CORS 설정, 다국어 처리(i18n) 등 웹 애플리케이션 전체에 공통으로 필요한 작업을 한곳에서 깔끔하게 처리할 수 있다.
② 컨트롤러의 단순화 (비즈니스 로직에 집중)
- 기존 문제점: 개발자가 HTTP Request/Response 객체를 직접 다루고 서블릿 API에 강하게 의존하여 코드가 복잡해짐.
- 개선점: 개발자는 서블릿의 내부 동작 방식(파라미터 파싱, 타입 변환 등)을 깊게 알지 못해도, 일반 자바 클래스(POJO)에 @Controller 또는 @RestController 어노테이션만 붙여 오직 비즈니스 로직 개발에만 집중할 수 있다.
③ 높은 유연성과 확장성 (유연한 컴포넌트 교체)
- 디스패처 서블릿 내부의 핵심 요소인 HandlerMapping, HandlerAdapter, ViewResolver, HttpMessageConverter 등이 모두 인터페이스로 추상화되어 있음.
- 덕분에 필요에 따라 표준 구현체를 원하는 기술(예: View 엔진을 JSP에서 Thymeleaf로 변경하거나, JSON 변환 라이브러리를 확장하는 등)로 손쉽게 교체하거나 확장할 수 있다.
④ Spring Boot 환경에서의 자동화 (Zero-Configuration)
- Spring Boot에서는 내장 웹 서버(Tomcat)와 DispatcherServlet을 자동으로 등록하고 설정(AutoConfiguration)해 준다.
- 따라서 개발자는 복잡한 web.xml 설정이나 Java Config 작성 없이, 프로젝트를 시작하자마자 곧바로 컨트롤러만 만들어 빠르게 개발을 진행할 수 있다.
'Tech Stack > Backend' 카테고리의 다른 글
| 🛡️자바 서블릿 기반의 HttpSession (세션) (0) | 2026.06.29 |
|---|---|
| 🥾src/test/java에서 시작하는 단위 테스트 환경 구축과 로깅 가이드 (0) | 2026.06.27 |
| 🥾 레거시와 Spring Boot 웹 서버 구동 방식 비교 (+ REST API) (0) | 2026.06.25 |
| 🐱순수 Jakarta EE 서블릿 환경에서 톰캣 연동 및 구동 테스트 (0) | 2026.06.24 |
| 🍃스프링, 자바 표준, 자카르타 세 진영의 어노테이션 비교 (0) | 2026.06.24 |