https://sundaland.tistory.com/59
[ ▶ DispatcherServlet ]
Spring MVC는 많은 다른 웹 프레임워크처럼 프론트 컨트롤러 패턴을 기반으로 설계되었다. 여기서 중앙 서블릿인 DispatcherServlet이 공유된 알고리즘을 사용하여 요청을 처리하고, 실제 작업은 구성 가능한 위임 컴포넌트들에 의해 수행된다. 이 모델은 유연하여 다양한 워크플로우를 지원한다.
DispatcherServlet은 다른 서블릿과 마찬가지로 서블릿 명세에 따라 선언되고 매핑되어야 한다. 이를 위해 Java 설정이나 web.xml을 사용할 수 있다. 설정이 완료되면, DispatcherServlet은 Spring 설정을 통해 필요한 위임 컴포넌트들을 찾는다. 예를 들어, http request를 처리하는 방법이나 Spring 설정을 통해 필요한 위임 컴포넌트들을 찾는다. 예를 들어, http request를 처리하는 방법이나 뷰를 어떻게 보여줄지, 예외를 어떻게 처리할지 들을 결정하는데 필요한 컴포넌트들이 있다.
▼ 서블릿 컨테이너가 자동으로 감지하는 DispatcherServlet을 등록하고 초기화하는 방법을 보여준다.
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Spring 웹 애플리케이션 구성 로드
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// DispatcherServlet 생성 및 등록
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
서블릿 컨테이너에서 DispatcherServlet을 자동으로 감지하고 설정하는 과정을 보여준다.
- AnnotationConfigWebApplicationContext: Spring 설정을 불러오는 역할을 한다.
- DispatcherServlet: 이 서블릿이 모든 요청을 처리하며, Spring의 다양한 컴포넌트를 사용해 실제 작업을 수행한다.
- 등록 과정: 서블릿 컨테이너에 이 서블릿을 등록하고, /app/* 경로에 매핑한다.
이렇게 하면 Spring MVC 애플리케이션의 요청 처리가 가능해진다.
ServletContext API를 직접 사용하는 것 외에도 AbstractAnnotationConfigDispatcherServletInitializer를 확장하고 특정 메서드를 오버라이드할 수 있다.
프로그램적으로 사용하는 경우 GenericWebApplicationContext를 AnnotationConfigWebApplicationContext 대신 사용할 수 있다.
아래의 web.xml 구성 예제는 DispatcherServlet을 등록하고 초기화한다.
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
Spring Boot는 다른 초기화 순서를 따른다. 서블릿 컨테이너의 라이프사이클에 연결하는 대신 Spring Boot는 Spring 구성을 사용해 스스로와 내장 서블릿 컨테이너를 부트스트랩한다. 필터와 서블릿 선언은 Spring 구성에서 감지되어 서블릿 컨테이너에 등록된다.
[ ▷ Context Hierarchy ]
DispatcherServlet은 자체 구성을 위해 WebApplicationContext (일반 ApplicationContext의 확장 버전)을 필요로 한다. WebApplicationContext는 ServletContext 및 해당 서블릿과 연결되어 있으며, 정적 메서드를 통해 애플리케이션에서 필요할 때 접근할 수 있다.
많은 애플리케이션에서는 단일 WebApplicationContext만 있으면 충분하다. 하지만 컨텍스트 계층 구조를 설정할 수 있는데, 이는 하나의 루트 WebApplicationContext가 여러 DispatcherServlet 또는 다른 서블릿 인스턴스와 공유되고, 각 서블릿은 별도의 자식 WebApplicationContext를 가진다. 루트 컨텍스트는 여러 서블릿이 공유하는 인프라 빈 (데이터 리포지토리, 비즈니스 서비스 등)을 포함하고, 자식 컨텍스트는 각 서블릿에 고유한 빈을 포함한다. 자식 컨텍스트에서는 루트 컨텍스트의 빈을 상속받아 사용할 수 있지만, 필요시 재정의할 수도 이다.
이 구조는 여러 서블릿 간에 공통 리소스를 공유하면서도, 각 서블릿이 고유한 설정을 유지할 수 있도록 해준다.
▼ WebApplicationContext 계층 구조를 구성
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}
※ 애플리케이션 컨텍스트 계층 구조가 필요하지 않은 경우, 모든 설정을 getRootConfigClasses() 메서드를 통해 반환하고, getServletConfigClasses()\ 메서드에서는 null을 반환할 수 있다.
▼ web.xml
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
※ 애플리케이션 컨텍스트 계층 구조가 필요하지 않은 경우, 애플리케이션은 루트 컨텍스트만 구성하고 contextConfigLocation 서블릿 파라미터를 비워둘 수 있다.
[ ▷ Special Bean Types ]
DispatcherServlet은 http request를 처리하고 적절한 http response을 렌도링하기 위해 특별한 빈에 위임한다. 여기서 Special Bean이란 Spring이 관리하는 객체 인스턴스를 의미하며, 이들은 프레임워크 contact\[interface\]를 구현한다. 이들 빈은 일반적으로 기본 인터페이스를 갖고 있지만, 속성을 커스터마이징하거나 확장 또는 교체할 수 있다.
빈 타임 | 설명 |
HandlerMapping | 요청을 핸들러에 매핑하고, 요청 전후에 실행될 인터셉터 목록을 연결한다. 매핑은 특정 기준에 따라 이루어지며, 각 HandlerMapping 구현에 따라 세부 사항이 다를 수 있다. RequestMappingHandlerMapping: @RequestMapping 주석이 달린 메서드를 지원하여 RESTful 요청을 처리한다. SimpleUrlHandlerMapping: URI 경로 패턴을 핸들러에 명시적으로 등록하여 요청을 처리한다. |
HandlerAdapter | 요청에 매핑된 핸들러를 호출하는 데 도움을 준다. 핸들러가 어떻게 호출되는지와 관계없이 DispatcherServlet이 핸들러를 호출할 수 있도록 해준다. 예를 들어, 주석이 달린 컨트롤러를 호출하려면 주석을 해석해야 한다. HandlerAdapter의 주요 목적은 이러한 세부사항으로부터 DispatcherServlet을 보호하는 것이다. |
HandlerExceptionResolver | 예외를 해결하기 위한 전략을 제공한다. 핸들러에 매핑하거나 HTML 오류 뷰 또는 기타 대상을 반환할 수 있다. 이 빈은 애플리케이션에서 발생한 예외를 처리하는 데 중요한 역할을 한다. |
ViewResolver | 핸들러에서 반환된 문자열 기반의 논리적 뷰 이름을 실제 뷰로 변환하여 응답을 렌더링하는 데 사용한다. 뷰 해상도(View Resolution) 및 뷰 기술에 대한 세부사항은 여기에서 다룬다. |
LocaleResolver LocaleContextResolver |
클라이언트가 사용하는 로케일과 시간대를 확인하여 국제화된 뷰를 제공할 수 있게 해준다. 이를 통해 사용자에게 맞춤형 콘텐츠를 제공할 수 있다. |
ThemeResolver | 웹 애플리케이션에서 사용할 수 있는 테마를 해결한다. 예를 들어, 개인화된 레이아웃을 제공할 수 있다. |
MultipartResolver | 브라우저 폼 파일 업로드와 같은 멀티파트 요청을 분석하기 위한 추상화이다. 멀티파트 파싱 라이브러리를 사용하여 요청을 처리한다. |
FlashMapManager | "입력" 및 "출력" FlashMap을 저장하고 검색하여, 주로 리다이렉트를 통해 한 요청에서 다른 요청으로 속성을 전달하는 데 사용한다. Flash 속성에 대한 처리를 지원한다. |
[ ▷ Web MVC Config ]
애플리케이션은 요청 처리를 위해 필요한 특별한 빈 유형 (Special Bean Types)을 선언할 수 있다. DispatcherServlet은 각 특별한 빈에 대해 WebApplicationContext를 확인한다. 만약 해당하는 빈 유형이 없다면, 기본적으로 DispatcherServlet.properties에 나열된 기본 유형으로 대체된다.
대부분의 경우, MVC 구성 (MVC Config)이 가장 좋은 출발점이다. 이는 필요한 빈을 Java 또는 XML로 선언하고, 이를 사용자 정의하기 위한 더 높은 수준의 구성 콜백 API를 제공한다.
Spring Boot는 Spring MVC를 구성하기 위해 MVC Java 구성을 기반으로 하며, 여러가지 추가적인 편리한 옵션을 제공한다.
[ ▷ Servlet Config ]
Servlet 환경에서는 web.xml을 사용하는 것 외에도 Servlet 컨테이너를 프로그래밍 방식으로 구성할 수 있는 옵션이 있다.
▼ DispatcherServlet을 등록하는 예제 (Java)
import org.springframework.web.WebApplicationInitializer;
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = container.addServlet("dispatcher",
new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
▼ DispatcherServlet을 등록하는 예제 (Kotlin)
import org.springframework.web.WebApplicationInitializer
class MyWebApplicationInitializer : WebApplicationInitializer {
override fun onStartup(container: ServletContext) {
val appContext = XmlWebApplicationContext()
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml")
val registration = container.addServlet("dispatcher", DispatcherServlet(appContext))
registration.setLoadOnStartup(1)
registration.addMapping("/")
}
}
[ ▷ WebApplicationInitializer ]
WebApplicationInitializer는 Spring MVC가 제공하는 인터페이스로, 구현이 자동으로 감지되어 Servlet 3 컨테이너를 초기화하는데 사용된다.
AbstractDispatcherServletInitializer라는 추상 기본 클래스는 DispatcherServlet을 등록하는 과정을 간소화한다. 이 클래스의 메서드를 오버라이드하여 서블릿 매핑 및 설정 위치를 지정할 수 있다.
▼ Java 기반 Spring 구성의 경우
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null; // 루트 설정 클래스 없음
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { MyWebConfig.class }; // 서블릿 설정 클래스
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" }; // 매핑 경로
}
}
▼ XML 기반 Spring 구성의 경
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
return null; // 루트 애플리케이션 컨텍스트 없음
}
@Override
protected WebApplicationContext createServletApplicationContext() {
XmlWebApplicationContext cxt = new XmlWebApplicationContext();
cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
return cxt; // XML 설정 사용
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" }; // 매핑 경로
}
}
[ ▷ 필터 추가 ]
AbstractDispatcherServletInitializer는 필터 인스턴스를 추가하고 이를 자동으로 DispatcherServlet에 매핑할 수 있는 편리한 방법도 제공한다.
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new HiddenHttpMethodFilter(),
new CharacterEncodingFilter()
}; // 필터 배열 반환
}
}
각 필터는 그 유형에 따라 기본 이름으로 추가되며 자동으로 DispatcherServlet에 매핑된다.
[ ▷ 비동기 지원 ]
AbstractDispatcherServletInitializer의 isAsyncSupported 메서드는 DispatcherServlet과 이를 매핑된 모든 필터에 대해 비동기 지원을 활성화하는 단일 위치를 제공한다. 기본적으로 이 플래그는 true로 설정된다.
[ ▷ DispatcherServlet 사용자 정의 ]
DispatcherServlet 자체를 추가로 사용자 정의해야 하는 경우, createDispatcherServlet 메서드를 오버라이드하여 설정할 수 있다.
[ ▷ Processing ]
[ ▷ DispatcherServlet 요청 처리 과정 ]
- WebApplicationContext 검색 및 바인딩: 요청 처리 과정에서 WebApplicationContext가 검색되어 요청의 속성으로 바인딩된다. 이 컨텍스트는 컨트롤러 및 다른 구성 요소들이 사용할 수 있다. 기본적으로 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE라는 키로 바인딩된다.
- locale resolver 바인딩: 요청에 로케일 리졸버가 바인딩되어, 요청 처리 시 어떤 로케일을 사용할지 결정한다 (예: 뷰 렌더링, 데이터 준비 등). 로케일 처리가 필요하지 않은 경우, 로케일 리졸버는 필요하지 않다.
- theme resolver 바인딩:요청에 테마 리졸버가 바인딩되어, 뷰와 같은 요소들이 사용할 테마를 결정한다. 테마를 사용하지 않는 경우, 이를 무시할 수 있다.
- multipart file resolver 검사: 멀티파트 파일 리졸버를 지정한 경우, 요청이 멀티파트인지 검사한다. 멀티파트가 발견되면, 요청은 MultipartHttpServletRequest로 래핑되어 다른 요소들이 추가 처리를 할 수 있도록 한다.
- Handler 검색: 적절한 핸들러를 검색한다. 핸들러가 발견되면, 핸들러와 관련된 실행 체인(전처리기, 후처리기, 컨트롤러)이 실행되어 렌더링할 모델을 준비한다. 또는, 주석이 달린 컨트롤러의 경우, 뷰를 반환하는 대신 HandlerAdapter 내에서 응답을 렌더링할 수 있다.
- 예외 해결: 요청 처리 중에 발생한 예외는 WebApplicationContext에 선언된HandlerExceptionResolver빈을 사용하여 해결한다. 이러한 예외 리졸버는 예외를 처리하기 위한 사용자 정의 로직을 허용한다.
- HTTP 캐싱 지원: 핸들러는 WebRequest의 checkNotModified 메서드를 사용하여 HTTP 캐싱을 지원할 수 있으며, 주석이 달린 컨트롤러에 대한 추가 옵션이 제공된다.
[ ▷ DispatcherServlet 초기화 파라미터 ]
DispatcherServlet 인스턴스를 사용자 정의하려면, web.xml 파일의 서블릿 선언에 Servlet 초기화 매개변수(init-param)를 추가할 수 있다.
매게변수 | 설명 |
contextClass | ConfigurableWebApplicationContext를 구현하는 클래스. 기본적으로 XmlWebApplicationContext가 사용된다. |
contextConfigLocation | 컨텍스트 인스턴스에 전달되는 문자열로, 컨텍스트가 위치하는 곳을 나타낸다. 여러 문자열을 사용하여 여러 컨텍스트를 지원할 수 있으며, 동일한 빈이 정의된 경우 최신 위치가 우선한다. |
namespace | WebApplicationContext의 네임스페이스이다. 기본값은 [servlet-name]-servlet이다. |
throwExceptionIfNoHandlerFound | 요청에 대한 핸들러가 발견되지 않았을 때 NoHandlerFoundException을 발생시킬지 여부를 결정한다. 이 예외는 HandlerExceptionResolver로 처리할 수 있다. (@ExceptionHandler 메서드 사용) 현재 6.1 버전에서 기본값은 true이며, 더 이상 사용되지 않는다. |
기타 주의사항 | 기본 서블릿 처리가 구성된 경우, 해결되지 않은 요청은 항상 기본 서블릿으로 전달되며, 404 오류는 발생하지 않는다. |
이렇게 DispatcherServlet은 요청을 처리하고, 요청 처리 과정에서 발생하는 다양한 요소들을 바인딩하고 관리한다.
[ ▷ Path Matching ]
Servlet API는 전체 요청 경로를 requestURI로 노출하여, 이를 contextPath, servletPath, pathInfo로 세분화한다. 이 값들은 서블릿이 어떻게 매핑되었는지에 따라 달라진다.
Spring MVC는 이러한 입력을 바탕으로 핸들러 매핑에 사용할 조회 경로 (Lookup path)를 결정해야 하며, 이 때 contextPath와 서블릿 매핑 접두사를 제외해야 한다.
△ 경로 처리의 문제점
◎ 서블릿 경로와 경로 정보의 디코딩
- servletPath와 pathInfo는 디코딩되어 있어, 전체 requestURI와 직접 비교하여 조회 경로를 유도하기가 어렵다. 그래서 requestURI를 디코딩해야 한다. 하지만 이는 보안 문제를 유발할 수 있는 인코딩된 예약 문자가 포함된 경로 구조를 변경할 수 있다.
- 예를 들어, 예약 문자게 '/' 또는 ';'가 디코딩될 경우, 경로 구조가 변경될 수 있다. 게다가 서블릿 컨테이너는 servletPath를 다양한 정도로 정규화하므로 requestURI와의 startsWith 비교가 어려워진다.
◎ 서블릿 경로 사용의 불리함
- 이러한 이유로, 서블릿 경로에 대한 의존도를 피하는 것이 좋다. 만약 DispatcherServlet이 기본 서블릿으로 '/' 또는 '/*'f로 매핑되어 있고 서블릿 컨테이너가 4.0 이상인 경우, Spring MVC는 서블릿 매핑 유형을 감지하고 servletPath와 pathInfo의 사용을 피할 수 있다.
- 3.1 서블릿 컨테이너의 경우, 동일한 서블릿 매핑 유형을 사용하면, MVC 구성에서 alwaysUseFullPath=true를 통해 UrlPathHepler를 제공하여 동일한 효과를 얻을 수 있다.
◎ 요청 URI 디코딩의 문제점
- 기본 서블릿 매핑 "/"는 좋은 선택이지만, 여전히 요청 URI를 디코딩해야 컨트롤러 매핑과 비교할 수 있다. 그러나 이는 예약 문자를 디코딩함으로써 경로 구조를 변경할 수 있다는 위험이 있다. 이러한 문자가 예상되지 않는 경우 (Spring Security HTTP 방화벽처럼) 이를 거부하거나, UrlPathHelper를 urlDecode=false로 구성할 수 있다. 그러나 이 경우 컨트롤러 매핑은 인코딩된 경로와 일치해야 하므로 잘 작동하지 않을 수 있다.
- 게다가, DispatcherServlet이 다른 서블릿과 URL 공간을 공유해야 하거나 매핑이 필요할 경우 접두사로 매핑해야 할 수 있다.
[ ▷ PathPatternParser의 도입 ]
이러한 문제는 Spring MVC의 5.3 버전부터 사용 가능한 PathPatternParser와 파싱된 패턴을 사용함으로써 해결된다. 이는 기본적으로 6.0 버전에서 활성화된다.
◎ PathPatternParser의 장점
- AntPathMatcher와 달리, PathPatternParser는 조회 경로를 디코딩하거나 컨트롤러 매핑을 인코딩할 필요 없이 패턴을 매칭할 수 있다. 이는 요청 경로(RequestPath)라고 불리는 경로의 파싱된 표현에 기반하여 경로의 각 세그먼트를 개별적으로 매칭한다.
- 이를 통해 경로 세그먼트 값을 개별적으로 디코딩하고 정리할 수 있으며, 경로 구조를 변경할 위험 없이 처리할 수 있다.
- 또한, 파싱된 패턴은 서블릿 경로 매핑을 접두사로 사용하는 것을 지원하며, 이 때 접두사는 간단해야 하며 인코딩된 문자가 없어야 한다.
이렇게 `PathPatternParser`와 파싱된 패턴을 사용함으로써 경로 일치의 문제를 효과적으로 해결할 수 있다. 이는 Spring MVC의 경로 처리 방식에 유연성과 안정성을 추가한다.
[ ▷ Interception ]
인터셉션은 모든 HandlerMapping 구현에서 지원되며, 요청 간에 기능을 적용할 때 유용하다. HandlerInterceptor를 사용하여 특정 요청 처리 전후에 코드를 실행할 수 있다.
◎ preHandle(..)
- 이 메서드는 실제 핸들러가 실행되기 전에 호출된다.
- 반환값이 true이면, 요청 처리 체인이 계속 진행되고, 핸들러가 호출 된 다.
- 반환값이 false이면, 나머지 실행 체인이 건너뛰어지며 핸들러가 호출되지 않는다.
- 주로 요청 인증, 세션 검사 등의 기능을 구현하는 데 사용된다.
◎ postHandle(..)
- 이 메서드는 핸들러가 실행된 후에 호출된다.
- 이 시점에서 모델 데이터나 뷰 정보를 조작할 수 있다.
- 주로 로깅이나 추가 데이터 추가 등을 위한 용도로 사용다.
◎ afterCompletion(..)
- 이 메서드는 요청 처리가 완전히 종료된 후에 호출된다.
- 주로 리소스 정리, 로그 기록 등을 위한 용도로 사용된다.
[ ▷ 주의사항 ]
◎ @ResponseBody 및 ResponseEntity 사용 시
- @ResponseBody 또는 ResponseEntity를 사용하는 컨트롤러 메서드의 경우, 응답은 HandlerAdapter 내에서 작성되고 커밋된다. 이 때문에 postHandle이 호출되기 전에 이미 응답이 완료되어, 추가 헤더를 추가하는 등의 변경은 불가능하다.
- 이러한 경우에는 ResponseBodyAdvice를 구현하고 이를 Controller Advice 빈으로 선언하거나 RequestMappingHandlerAdapter에 직접 구성하여 사용해야 한다.
[ ▷ 인터셉터 구성 ]
- 인터셉터를 구성하는 방법에 대한 예시는 MVC 구성의 Interceptors 섹션을 참고하면 된다.
- 또한, 개별 HandlerMapping 구현에서 setter를 사용하여 인터셉터를 직접 등록할 수도 있다.
[ ▷ 경고 ]
- 인터셉터는 보안 계층으로 사용하는 것이 이상적이지 않다. 왜냐하면 주석 기반 컨트롤러의 경로 매칭과의 불일치가 발생할 수 있기 때문이다.
- 일반적으로 Spring Security를 사용하는 것을 추천하며, 대안으로 Servlet 필터 체인과 통합된 유사한 접근 방식을 조기에 적용하는 것이 좋다.
인터셉터는 요청의 전처리, 후처리 및 요청 완료 후 처리를 가능하게 하여, 코드 재사용성과 요청 흐름의 제어를 쉽게 해준다. 하지만 보안 기능을 구현할 때는 다른 메커니즘을 사용하는 것이 바람직하다.
[ ▷ Exceptions ]
Spring MVC에서 요청 매핑 중에 예외가 발생하거나 요청 핸들러(@Controller)에서 예외가 던져지면, DispatcherServlet은 HandlerExceptionResolver 빈 체인에 위임하여 예외를 처리한다. 이 과정에서 대개는 오류 응답을 제공한다.
[ 참조 ] : https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-servlet.html
'Web on Servlet Stack' 카테고리의 다른 글
Enable MVC Configuration (0) | 2024.10.15 |
---|---|
Functional Endpoints [Serving Resources,Running a Server,Filtering Handler Functions] (0) | 2024.10.14 |
RounterFunction (0) | 2024.10.14 |
Functional Endpoints Overview (0) | 2024.10.14 |
Exceptions (0) | 2024.10.14 |