
안녕하세요. IT 기술 블로거입니다.
Spring Boot로 개발을 하다 보면 이런 궁금증이 생깁니다.
“브라우저에서 엔터를 치는 순간, 내 컨트롤러의 메서드까지 어떻게 도달하는 걸까? 그리고 내가 반환한 객체는 어떻게 JSON으로 바뀌어 나가는 걸까?”
이 과정을 이해하는 것은 고급 백엔드 개발자로 거듭나기 위한 필수 관문입니다. 내부 동작을 알아야 필터(Filter), 인터셉터(Interceptor), 예외 처리(Exception Handling) 등을 적재적소에 활용할 수 있기 때문입니다.
오늘은 Spring MVC의 핵심인 DispatcherServlet을 중심으로, 요청부터 응답까지의 전체 라이프사이클을 파헤쳐 보겠습니다.
1. Spring MVC의 심장: DispatcherServlet
Spring Boot 웹 모듈의 중심에는 DispatcherServlet이 있습니다. 모든 HTTP 요청을 한곳에서 받아 적절한 곳으로 배분해 주는 ‘중앙 컨트롤러(Front Controller)’ 역할을 합니다.
2. 요청 처리 7단계 (The Lifecycle)
클라이언트의 요청이 들어오면 다음 순서로 처리가 진행됩니다.
- DispatcherServlet 접수: 클라이언트의 HTTP 요청을 가장 먼저 받습니다.
- Handler Mapping: 이 요청을 처리할 수 있는 컨트롤러가 누구인지 찾습니다. (보통
@RequestMapping정보를 뒤집니다.) - Handler Adapter: 찾아낸 컨트롤러의 메서드를 실행할 수 있는 어댑터를 찾습니다. 어댑터가 실제 컨트롤러 메서드를 호출합니다.
- 비즈니스 로직 수행: 컨트롤러 -> 서비스 -> 리포지토리 순으로 로직이 돌아갑니다.
- ModelAndView / 데이터 반환: 로직 결과를 반환합니다.
- HTML 페이지면 뷰 이름을 반환하고,
- REST API면 객체 그 자체를 반환합니다.
- Message Converter / View Resolver:
- 데이터라면 JSON으로 변환(HttpMessageConverter)하고,
- 화면이라면 HTML로 렌더링(ViewResolver)합니다.
- Response 전달: 최종 결과를 HTTP 응답 본문에 실어 클라이언트에게 보냅니다.
3. 실무 코드 예제: 흐름 제어 (Interceptor)
요청과 응답 사이에서 공통적인 로직(로그 출력, 권한 체크 등)을 처리하고 싶을 때 Interceptor를 사용합니다.
예제 1: 로그 기록을 위한 인터셉터
@Slf4j
@Component
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
log.info(">>> [요청 시작] URI: {}", request.getRequestURI());
return true; // true여야 컨트롤러로 넘어갑니다.
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
log.info("<<< [컨트롤러 완료]");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
log.info("=== [응답 완료]");
}
}
예제 2: 인터셉터 등록 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**") // 모든 경로에 적용
.excludePathPatterns("/css/**", "/js/**"); // 정적 리소스 제외
}
}
4. 필터(Filter) vs 인터셉터(Interceptor)
요청 흐름 중에 가로채는 기능이라는 점은 같지만, 실행 시점이 다릅니다.
- Filter: 서블릿 컨테이너(Tomcat) 레벨에서 동작합니다. Spring 바깥이므로 보안 처리(Spring Security), 인코딩 변환 등에 쓰입니다.
- Interceptor: Spring MVC 레벨에서 동작합니다. 컨트롤러 호출 전후에 실행되므로 로그인 체크, 상세한 로그 기록 등에 쓰입니다.

결론
Spring Boot의 요청 처리 흐름은 “DispatcherServlet이라는 중앙 통제소에서 어댑터를 통해 비즈니스 로직을 연결해 주는 과정”입니다. 이 흐름 사이사이에 필터와 인터셉터가 존재하여 공통 로직을 처리합니다.
이 구조를 이해하면 “왜 내 요청이 컨트롤러까지 안 올까?” 혹은 “응답 데이터 포맷이 왜 이럴까?” 같은 문제를 디버깅할 때 훨씬 빠르고 정확하게 원인을 찾을 수 있습니다.
다음 시간에는 이 흐름 중에서 가장 마법 같은 부분인 “객체가 어떻게 자동으로 JSON으로 변환되는가?”에 대해 심층 분석해 보겠습니다.





