🌐 [Spring] 웹 요청 처리의 핵심, dispatcher-servlet.xml 완벽 분석 (Java Config 전환 포함)
web.xml 분석에 이어, 오늘은 Spring MVC의 실질적인 웹 동작을 정의하는 심장부, dispatcher-servlet.xml 파일에 대해 깊이 있게 파헤쳐 보겠습니다.
web.xml이 웹 서버(Tomcat)에게 "모든 요청을 DispatcherServlet에게 넘겨!"라고 지시했다면, 이 dispatcher-servlet.xml 파일은 DispatcherServlet에게 "요청을 받으면 이렇게 처리해!" 라고 상세한 행동 강령을 알려주는 역할을 합니다. 즉, 컨트롤러를 찾고, 뷰(View)를 연결하고, 어노테이션을 동작시키는 모든 마법이 바로 여기서 시작됩니다.
📝 전체 코드 살펴보기
먼저 분석할 dispatcher-servlet.xml 파일의 전체 코드입니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1. Component Scan: 컨트롤러를 찾아서 빈으로 등록 -->
<context:component-scan base-package="com.example.controller" />
<!-- 2. Enable MVC: 어노테이션 기반 MVC 기능 활성화 -->
<mvc:annotation-driven />
<!-- 3. View Resolver: 뷰(JSP) 경로를 완성 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 4. Static Resources: 정적 리소스(CSS, JS, 이미지 등) 처리 위임 -->
<mvc:default-servlet-handler />
</beans>
📝 핵심 설정 분석
이 파일은 크게 4가지의 핵심적인 역할을 수행하도록 구성되어 있습니다.
1. 컴포넌트 스캔 (Component Scan)
<context:component-scan base-package="com.example.controller" />
• 역할: Spring 컨테이너에게 지정된 패키지(com.example.controller)를 스캔하여 특정 어노테이션(@Controller, @Service 등)이 붙은 클래스를 찾아 자동으로 빈(Bean)으로 등록하라고 지시합니다.
• 핵심: 이 설정 덕분에 우리는 컨트롤러 클래스를 만들고 @Controller 어노테이션만 붙이면, Spring이 알아서 해당 객체를 관리해 주므로 XML에 일일이 빈을 등록하는 수고를 덜 수 있습니다.
2. MVC 기능 활성화 (Enable MVC)
<mvc:annotation-driven />
• 역할: 마법의 한 줄입니다. 어노테이션 기반의 현대적인 Spring MVC 기능을 사용하기 위한 필수 설정입니다.
• 주요 기능: 이 태그 하나가 보이지 않는 곳에서 다음과 같은 필수적인 빈들을 등록하고 활성화합니다.
• @RequestMapping, @GetMapping 등을 처리하는 RequestMappingHandlerMapping.
• 컨트롤러 메서드를 호출하고 파라미터(@RequestParam 등)를 처리하는 RequestMappingHandlerAdapter.
• JSON 데이터 변환, 데이터 검증(@Valid) 등 다양한 고급 기능.
• 결론: 이 태그가 없으면 @RequestMapping을 비롯한 대부분의 Spring MVC 어노테이션이 동작하지 않습니다.
3. 뷰 리졸버 (View Resolver)
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
• 역할: 컨트롤러가 반환하는 **논리적인 뷰 이름(Logical View Name)**을 실제 물리적인 뷰 파일 경로로 완성해주는 역할을 합니다.
• 동작 방식:
1.컨트롤러가 return "home"; 과 같이 문자열을 반환합니다.
2.ViewResolver는 이 "home"이라는 문자열을 받아, 설정된 prefix와 suffix를 앞뒤에 붙입니다.
3.최종적으로 /WEB-INF/views/ + home + .jsp = /WEB-INF/views/home.jsp 라는 실제 파일 경로를 만들어 줍니다.
4. 정적 리소스 처리 (Static Resources)
<mvc:default-servlet-handler />
• 역할: CSS, JavaScript, 이미지 파일 등 동적인 처리가 필요 없는 정적 리소스에 대한 요청을 처리합니다.
• 문제점: web.xml에서 DispatcherServlet의 처리 경로를 /로 지정하면, /css/style.css 같은 정적 파일 요청까지 DispatcherServlet이 가로채게 됩니다. DispatcherServlet은 이 요청을 처리할 컨트롤러를 찾지 못해 404 에러를 발생시킵니다.
• 해결책: 이 태그는 "만약 들어온 요청을 처리할 컨트롤러 매핑이 없다면, 그 요청을 Spring이 처리하지 말고 원래 웹 서버(Tomcat)의 기본 서블릿에게 넘겨라" 라고 설정합니다. 그러면 웹 서버가 정적 파일을 올바르게 찾아 클라이언트에게 제공할 수 있습니다.
📝 더 나은 코드를 향하여: Java 기반 설정으로의 완전한 전환
XML 설정은 직관적이지만, 현대적인 Spring 개발에서는 타입 안정성(type-safe)과 리팩토링 용이성이 뛰어난 **Java 기반 설정(Java-based Configuration)**을 사용하는 것이 표준입니다.
아래와 같이 web.xml과 dispatcher-servlet.xml을 모두 제거하고 순수 Java 코드로 프로젝트를 설정할 수 있습니다
1단계: dispatcher-servlet.xml을 대체할 WebConfig 클래스 생성
먼저, dispatcher-servlet.xml의 모든 기능을 수행하는 Java 설정 클래스를 만듭니다.
// WebConfig.java
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc // <mvc:annotation-driven /> 역할
@ComponentScan(basePackages = "com.example.controller") // <context:component-scan /> 역할
public class WebConfig implements WebMvcConfigurer {
// InternalResourceViewResolver 빈 등록
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
// <mvc:default-servlet-handler /> 역할
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
2단계: web.xml을 대체할 MyWebAppInitializer 클래스 생성
다음으로, web.xml의 역할을 수행하며 위에서 만든 WebConfig를 로드하는 초기화 클래스를 만듭니다. 이 방법을 사용하면 web.xml 파일을 프로젝트에서 완전히 삭제할 수 있습니다.
//MyWebAppInitializer.java
package com.example.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// Root ApplicationContext에 대한 설정 (Service, Repository 등). 현재는 없으므로 null.
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
// DispatcherServlet의 Servlet ApplicationContext에 대한 설정 (Controller, ViewResolver 등)
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebConfig.class};
}
// DispatcherServlet이 처리할 요청 경로 지정
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 인코딩 필터 설정
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[]{encodingFilter};
}
}
🎯 마무리
오늘은 Spring MVC의 웹 요청 처리 로직을 담당하는 dispatcher-servlet.xml을 분석하고, 이를 현대적인 Java 설정으로 전환하는 방법까지 알아보았습니다.
요약:
1.component-scan: @Controller를 찾아 빈으로 등록합니다.
2.annotation-driven: @RequestMapping 등 MVC 어노테이션을 활성화합니다.
3.ViewResolver: 컨트롤러가 반환한 뷰 이름을 실제 JSP 파일 경로로 완성합니다.
4.default-servlet-handler: CSS, JS 같은 정적 리소스 요청을 처리합니다.
비록 Spring Boot가 많은 부분을 자동화해주지만, 그 내부에서 어떤 일들이 일어나는지 이해하는 것은 문제 해결 능력과 애플리케이션 설계 능력을 한 단계 끌어올리는 데 큰 도움이 됩니다. 이 글이 여러분의 Spring 학습에 도움이 되었기를 바랍니다
'Java > Spring Framework' 카테고리의 다른 글
| Spring Boot 없이 IntelliJ 유료버전으로 전통적인 Spring MVC 프로젝트 구성하기 (2) | 2025.08.29 |
|---|---|
| [Spring] 스프링 MVC의 심장, web.xml 완벽 분석 (DispatcherServlet, 한글 필터) (2) | 2025.08.29 |
| [Maven] Spring 프로젝트의 설계도, pom.xml 완벽 해부 (2) | 2025.08.29 |