스프링 웹 애플리케이션을 개발하다 보면 컨트롤러만 만들고 어노테이션만 붙이다 보면 “요청이 들어와서 응답이 나갈 때까지, 스프링 내부에서는 어떤 일이 일어날까?”가 궁금해지죠. 이번 글에서는 Spring MVC의 전체 요청 처리 프로세스를 한 번 정리해보려고 합니다.
Spring MVC란 무엇인가?
Spring MVC는 이름 그대로 Model, View, Controller 구조로 웹 애플리케이션을 구성하는 웹 프레임워크입니다. 클라이언트의 HTTP 요청을 받아서 컨트롤러로 전달하고, 비즈니스 로직을 수행한 뒤 View(화면)를 렌더링해서 응답을 돌려주는 일을 담당합니다. 우리가 주로 작성하는 것은 @Controller, @RestController 같은 컨트롤러 코드이지만, 그 뒤에서는 DispatcherServlet, HandlerMapping, ViewResolver 같은 여러 컴포넌트들이 함께 동작합니다.
핵심 컴포넌트 정리
- DispatcherServlet : 모든 요청의 입구이자 출구. Spring MVC의 프론트 컨트롤러 역할.
- HandlerMapping : 어떤 URL을 어떤 컨트롤러 메서드가 처리할지 찾아주는 매핑 정보.
- HandlerAdapter : 찾은 컨트롤러를 실제로 호출해 주는 어댑터.
- Controller : 요청을 받아 Service를 호출하고, 모델 데이터와 뷰 이름을 반환.
- Service / Repository : 비즈니스 로직, DB 접근을 담당하는 레이어.
- ViewResolver : 컨트롤러가 넘겨준 뷰 이름을 실제 View 파일로 찾아주는 역할.
- View (JSP/Thymeleaf 등) : 최종적으로 HTML을 만들어서 브라우저에 전달하는 화면 부분.
각 컴포넌트가 역할을 나눠 가지기 때문에, 컨트롤러 코드에서는 “무엇을 할지”에만 집중할 수 있고 “요청이 어떻게 들어왔는지, 뷰가 어떻게 렌더링되는지” 같은 부분은 Spring MVC가 대신 처리해 줍니다.
Spring MVC 요청 처리 흐름 한눈에 보기

- Client → DispatcherServlet (요청 전송) : 브라우저(클라이언트)가 /users/list 같은 URL로 요청을 보냅니다. 이 요청은 Front Controller 패턴의 핵심 요소인 DispatcherServlet이 가장 먼저 받습니다.
- DispatcherServlet → HandlerMapping (핸들러 조회) : DispatcherServlet은 요청 URL을 보고 “어떤 Controller가 이 요청을 처리해야 하지?”를 판단하기 위해 HandlerMapping에게 확인합니다.
- HandlerMapping → DispatcherServlet (핸들러 반환) : HandlerMapping은 URL 패턴에 맞는 Controller 메서드 정보(Handler)를 찾아서 돌려줍니다.
- DispatcherServlet → Controller (핸들러 호출) : DispatcherServlet은 이제 찾은 Controller 메서드를 실행하고 Controller는 비즈니스 로직을 처리한 뒤 Model + View 이름을 반환합니다.
- DispatcherServlet → ViewResolver (View 이름으로 실제 View 조회) : Controller가 반환한 "user/list"와 같은 뷰 논리 이름(logical view name)을 DispatcherServlet이 ViewResolver로 전달합니다. ViewResolver는 실제 View 파일 위치(템플릿 파일)를 결정합니다.
- ViewResolver → DispatcherServlet / DispatcherServlet → View (렌더링 준비) : ViewResolver가 알맞은 View 객체(JSP, Thymeleaf 등)를 반환하고, DispatcherServlet은 View에게 모델 데이터를 전달하며 렌더링을 요청합니다.
- View → Client (응답 반환) : View는 HTML 등 렌더링된 결과를 HTTP Response로 만들어 클라이언트에게 보냅니다.
요청 하나가 처리되는 실제 흐름
조금 더 구체적으로, /members URL로 GET 요청이 들어온다고 가정해 보겠습니다.
- 클라이언트 요청 브라우저에서
GET /members요청을 전송합니다. - DispatcherServlet이 요청 수신 웹 애플리케이션의
web.xml또는 스프링 부트 자동 설정에 의해 모든 요청이 먼저DispatcherServlet으로 전달됩니다. - HandlerMapping으로 컨트롤러 탐색
HandlerMapping이 현재 URL(/members)과 HTTP 메서드(GET)에 매핑된 컨트롤러 메서드를 찾아냅니다. (예:MemberController.list()) - HandlerAdapter로 컨트롤러 호출 찾은 컨트롤러가
@RequestMapping기반인지,@Controller인지 등에 따라 알맞은HandlerAdapter가 선택되고, 이 어댑터가 컨트롤러 메서드를 실제로 호출합니다. - Controller → Service → Repository 실행 컨트롤러는 서비스/레포지토리를 호출해 비즈니스 로직과 DB 조회 등을 수행하고 결과를
Model에 담아 반환합니다. - 뷰 이름 & 모델 반환 컨트롤러는 문자열 형태의 뷰 이름(예:
"members/list")과 모델 데이터를 DispatcherServlet에 돌려줍니다. - ViewResolver가 View 선택
ViewResolver가"members/list"라는 뷰 이름을 보고 실제 JSP/Thymeleaf 파일 위치를 결정합니다. (예:/WEB-INF/views/members/list.jsp) - View 렌더링 & 응답 반환 선택된 View가 모델 데이터를 이용해 HTML을 렌더링하고, 최종 결과가 HTTP 응답으로 클라이언트에게 전달됩니다.
예제 : 간단한 Spring MVC 컨트롤러
위 흐름이 실제 코드에서 어떻게 보이는지, 간단한 예제로 살펴보겠습니다.
@Controller
@RequestMapping("/members")
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
// 회원 목록 조회
@GetMapping
public String list(Model model) {
List<Member> members = memberService.findAll();
model.addAttribute("members", members);
return "members/list"; // View 이름
}
}
이 코드는 단순히 서비스 호출 + 모델 데이터 저장 + 뷰 이름 반환만 하고 있을 뿐이지만, 실제로는 그 앞뒤에서 DispatcherServlet, HandlerMapping, ViewResolver 등이 모두 함께 움직이면서 하나의 HTTP 요청을 완성된 HTML 응답으로 만들어줍니다.
Spring MVC의 장점
- 역할 분리 : 요청 분배, 비즈니스 로직, 뷰 렌더링 역할이 명확히 나뉘어 있습니다.
- 유연한 뷰 기술 : JSP, Thymeleaf, Freemarker 등 다양한 뷰 엔진과 연동 가능합니다.
- 강력한 확장성 : HandlerInterceptor, AOP, 필터 등과 결합해 부가 기능을 쉽게 확장할 수 있습니다.
- 테스트 용이성 : 컨트롤러/서비스/레포지토리를 계층별로 나눠 테스트하기 편리합니다.
특히 DispatcherServlet을 중심으로 한 일관된 처리 흐름 덕분에, 요청이 어디서 어떻게 처리되는지 한 번 구조를 이해해 두면 복잡한 서비스도 훨씬 수월하게 관리할 수 있습니다.
'ETC. > Spring' 카테고리의 다른 글
| [Spring] 스프링 JPA란 무엇인가? - 동작 원리와 처리 흐름 정리 (0) | 2025.11.19 |
|---|---|
| [Spring] 스프링 MyBatis란 무엇인가? - 동작 원리와 처리 흐름 정리 (0) | 2025.11.18 |
| [Spring] 스프링 AOP(Aspect Oriented Programming, 관점 지향 프로그래밍) (1) | 2025.11.16 |
| [Spring] 스프링 IoC(제어의 역전), DI(의존성 주입) 완벽 이해하기 (0) | 2025.11.15 |