DispatcherServlet과 Front Controller
3줄 요약
- Spring MVC가 처리하는 요청은 Servlet Container와 Filter Chain을 지난 뒤 중심 진입점인 DispatcherServlet을 통과한다.
- DispatcherServlet은 요청을 직접 처리하기보다 HandlerMapping, HandlerAdapter, ViewResolver 같은 전략 객체에 위임한다.
- 이 구조 덕분에 공통 웹 흐름은 중앙화되고, 실제 처리 책임은 확장 가능한 컴포넌트로 분리된다.
핵심 정리
- DispatcherServlet은 Front Controller 패턴의 구현체다.
- 요청의 시작점은 Controller가 아니라 Servlet Container와 DispatcherServlet이다.
- DispatcherServlet은 요청을 받고, 핸들러 실행 체인을 찾고, 실행하고, 결과를 해석하고, 뷰 렌더링 또는 응답 작성을 조율한다.
- Controller는 비즈니스 로직의 전체 실행자가 아니라 웹 요청을 애플리케이션 서비스로 연결하는 어댑터에 가깝다.
- 기존 MVC 문서의 “모든 HTTP 요청의 중앙 수신 및 분산 처리” 내용은 이 구조의 핵심이다.
헷갈리는 지점
- Controller가 HTTP 요청의 첫 도착지라고 생각하기 쉽다. 개발자가 작성하는 코드가 Controller라서 그렇게 느껴지기 때문이다.
- 핵심은 Controller 앞에 Servlet Container, Filter, DispatcherServlet이 있다는 점이다.
- Controller는 MVC 인프라가 선택하고 실행하는 핸들러다.
- DispatcherServlet이 모든 일을 직접 처리한다고 오해하기 쉽다. 이름상 중앙 객체처럼 보이기 때문이다.
- 핵심은 DispatcherServlet은 지휘자이고 실제 검색, 실행, 변환, 렌더링은 전략 객체가 맡는다는 점이다.
- 이 위임 구조가 Spring MVC 확장성의 핵심이다.
- MVC 요청 흐름을 암기 순서로만 외우기 쉽다. 컴포넌트 이름이 많기 때문이다.
- 핵심은 “찾기, 실행, 결과 해석, 응답 작성”이라는 책임 흐름으로 보는 것이다.
- HandlerMapping은 찾고, HandlerAdapter는 실행하며, ViewResolver나 MessageConverter가 응답을 완성한다.
확인 질문
- DispatcherServlet의 역할은 무엇인가?
- HTTP 요청을 중앙에서 받아 MVC 전략 객체에게 위임하며 전체 요청 처리 흐름을 조율한다.
- HandlerMapping은 무엇을 하는가?
- HandlerAdapter는 왜 필요한가?
- 다양한 Handler 타입을 DispatcherServlet이 일관된 방식으로 실행할 수 있게 해준다.
HandlerMapping과 HandlerAdapter
3줄 요약
- HandlerMapping은 현재 요청을 처리할 Handler를 찾는다.
- HandlerAdapter는 찾은 Handler를 실제로 실행한다.
- 검색과 실행을 분리하기 때문에 Spring MVC는 다양한 컨트롤러 방식과 핸들러 타입을 지원할 수 있다.
핵심 정리
- HandlerMapping은 URL, HTTP Method, header, consumes, produces 같은 조건을 바탕으로 Handler를 고르고, 보통 Interceptor가 포함된 HandlerExecutionChain을 반환한다.
- Handler라는 말은
@Controller 메서드만이 아니라 요청을 처리할 수 있는 더 넓은 대상을 의미한다.
- HandlerAdapter는 선택된 Handler의 호출 방식을 표준화한다.
@RequestMapping 기반 메서드는 RequestMappingHandlerAdapter가 실행한다.
- annotated controller에서는 HandlerAdapter 안에서 반환값 처리가 끝나 response body가 바로 작성될 수 있으므로, 항상 ViewResolver 단계로 간다고 보면 안 된다.
- 기존 MVC 문서의 “HandlerMapping URL 기반 핸들러 검색”과 “HandlerAdapter 핸들러 실행 표준 인터페이스”는 이 한 쌍으로 묶어 이해하면 된다.
헷갈리는 지점
- HandlerMapping이 Controller를 실행한다고 생각하기 쉽다. 요청과 Controller를 연결하므로 실행까지 할 것처럼 보이기 때문이다.
- 핵심은 HandlerMapping은 찾기만 한다는 점이다.
- 실행은 HandlerAdapter의 책임이다.
- Handler라는 용어를 Controller와 동일시하기 쉽다. 대부분의 예제가
@Controller 메서드를 보여주기 때문이다.
- 핵심은 Handler가 Controller보다 넓은 개념이라는 점이다.
- Spring MVC는 정적 리소스 핸들러, HttpRequestHandler 등 여러 Handler 모델을 지원한다.
- HandlerAdapter가 불필요한 중간 계층처럼 느껴지기 쉽다. Controller 메서드를 그냥 호출하면 될 것처럼 보이기 때문이다.
- 핵심은 Controller 메서드의 파라미터 해석과 반환값 처리를 표준화해야 한다는 점이다.
- HandlerAdapter가 ArgumentResolver와 ReturnValueHandler를 사용해 그 복잡성을 감춘다.
확인 질문
- HandlerMapping과 HandlerAdapter의 차이는 무엇인가?
- HandlerMapping은 요청에 맞는 Handler를 찾고, HandlerAdapter는 그 Handler를 실행한다.
@RequestMapping 메서드는 주로 어떤 Adapter가 실행하는가?
RequestMappingHandlerAdapter가 실행한다.
- 검색과 실행을 분리하는 장점은 무엇인가?
- 다양한 Handler 타입을 DispatcherServlet 구조를 바꾸지 않고 지원할 수 있다.
Request Response Cycle
3줄 요약
- 요청은 DispatcherServlet, HandlerMapping, HandlerAdapter, Controller, Service, 응답 처리 단계를 거친다.
- Controller 메서드의 파라미터는 ArgumentResolver가 만들고, 반환값은 ReturnValueHandler가 해석한다.
- 응답은 HTML View 렌더링 또는 HTTP MessageConverter 기반 body 작성으로 나뉜다.
핵심 정리
- Controller는 요청 파라미터를 직접 파싱하는 저수준 객체가 아니라 선언적 메서드 시그니처로 요청 데이터를 받는다.
- HandlerAdapter는 Controller 메서드를 호출하기 전에 필요한 인자를 준비한다.
- Service 호출과 Model 구성은 Controller의 일반적인 책임이지만, 비즈니스 규칙은 Service로 위임하는 편이 좋다.
- 반환값이 view name이면 ViewResolver 흐름으로 가고,
@ResponseBody, @RestController, ResponseEntity이면 MessageConverter 흐름으로 간다.
- 기존 MVC 문서의 Request Response Cycle 4개 문서는 이 흐름을 단계별로 풀어쓴 자료다.
헷갈리는 지점
- Controller 메서드 파라미터가 자동으로 생기는 이유를 단순 마법으로 보기 쉽다. 선언만 하면 값이 들어오기 때문이다.
- 핵심은 HandlerAdapter 내부의 HandlerMethodArgumentResolver들이 각 파라미터를 해석한다는 점이다.
@RequestParam, @PathVariable, @RequestBody, Model은 서로 다른 resolver 경로를 탄다.
- 반환값이 항상 View 이름이라고 생각하기 쉽다. 전통적인 MVC 예제의 영향 때문이다.
- 핵심은 반환값 처리 방식이 애너테이션과 타입에 따라 달라진다는 점이다.
- REST API에서는 MessageConverter를 통해 body가 작성되는 경우가 많다.
String 반환을 항상 문자열 body라고 생각하기 쉽다. Java 타입만 보면 문자열처럼 보이기 때문이다.
- 핵심은
@ResponseBody나 @RestController 맥락이 없으면 String은 보통 view name으로 해석된다는 점이다.
- 같은
String이라도 서버 렌더링 Controller인지 REST Controller인지에 따라 응답 경로가 달라진다.
- Controller에서 Service를 부르는 것이 단순 코드 분리라고만 느끼기 쉽다. 계층 구조를 형식처럼 보기 때문이다.
- 핵심은 웹 관심사와 비즈니스 관심사를 분리하는 것이다.
- Controller는 HTTP와 애플리케이션 서비스를 연결하고, Service는 업무 규칙을 수행한다.
확인 질문
- Controller 메서드 인자는 누가 준비하는가?
- HandlerAdapter가 HandlerMethodArgumentResolver들을 사용해 준비한다.
- JSON 응답은 보통 어떤 경로로 작성되는가?
@ResponseBody나 ResponseEntity 반환값을 HttpMessageConverter가 직렬화해 작성한다.
- Controller가 비즈니스 로직을 모두 가지면 어떤 문제가 생기는가?
- HTTP 처리와 업무 규칙이 섞여 Fat Controller가 되고 테스트와 재사용이 어려워진다.
ViewResolver와 MessageConverter
3줄 요약
- ViewResolver는 논리적 view 이름을 실제 View로 해석한다.
- HttpMessageConverter는 요청 body를 객체로 읽거나 객체를 응답 body로 쓴다.
- 서버 렌더링 MVC와 REST API는 같은 DispatcherServlet 위에서 서로 다른 반환값 처리 흐름을 탄다.
핵심 정리
- Controller가 문자열 view 이름을 반환하면 ViewResolver가 물리 view를 찾는다.
- Thymeleaf, JSP 같은 템플릿 렌더링은 ViewResolver 흐름과 연결된다.
@ResponseBody, @RestController, ResponseEntity는 view 렌더링이 아니라 response body 작성 흐름으로 간다.
- JSON 변환은 Jackson 같은 converter가 담당한다.
- 같은 URL 요청이라도 Accept header, produces 조건, 반환 타입에 따라 응답 처리 방식이 달라질 수 있다.
헷갈리는 지점
- 문자열 반환이 항상 문자열 응답 body라고 생각하기 쉽다. Java 메서드가 String을 반환하기 때문이다.
- 핵심은
@ResponseBody가 없으면 문자열은 보통 view name으로 해석될 수 있다는 점이다.
- REST API에서 문자열 body를 원하면
@ResponseBody나 @RestController 맥락을 확인해야 한다.
- ViewResolver와 MessageConverter를 같은 응답 변환기로 보기 쉽다. 둘 다 응답 생성에 관여하기 때문이다.
- 핵심은 ViewResolver는 화면 렌더링, MessageConverter는 HTTP body 변환이라는 점이다.
- HTML 페이지와 JSON API의 응답 경로를 분리해서 생각해야 한다.
@RestController를 단순히 @Controller의 최신 버전으로 보기 쉽다. REST API에서 자주 쓰기 때문이다.
- 핵심은
@RestController가 @Controller와 @ResponseBody를 합친 의미라는 점이다.
- view name을 반환하려는 Controller에는 일반
@Controller가 더 적합하다.
확인 질문
- ViewResolver는 무엇을 하는가?
- 논리적 view 이름을 실제 View 객체나 물리 경로로 해석한다.
- HttpMessageConverter는 무엇을 하는가?
- HTTP 요청 body를 객체로 읽거나 객체를 HTTP 응답 body로 쓴다.
@RestController의 핵심 의미는 무엇인가?
- 모든 handler method에
@ResponseBody 의미가 적용되어 반환값이 응답 body로 처리된다.