DispatcherSevlet의 기본전략과 여러가지 유형에 대해서 알아보자.
DispatcherServlet 기본전략
protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}
DispatcherServlet 의 초기화 전략은 다음과 같다. 초기화 구조는 거의다 비슷하기 때문에 여기에서는 initViewResolvers(context) 를 살펴보자.
	/**
	 * Initialize the ViewResolvers used by this class.
	 * <p>If no ViewResolver beans are defined in the BeanFactory for this
	 * namespace, we default to InternalResourceViewResolver.
	 */
	private void initViewResolvers(ApplicationContext context) {
		this.viewResolvers = null;
		if (this.detectAllViewResolvers) {
			// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
			Map<String, ViewResolver> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.viewResolvers = new ArrayList<>(matchingBeans.values());
				// We keep ViewResolvers in sorted order.
				AnnotationAwareOrderComparator.sort(this.viewResolvers);
			}
		}
		else {
			try {
				ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
				this.viewResolvers = Collections.singletonList(vr);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default ViewResolver later.
			}
		}
		// Ensure we have at least one ViewResolver, by registering
		// a default ViewResolver if no other resolvers are found.
		if (this.viewResolvers == null) {
			this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No ViewResolvers declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}
크게 this.detectAllViewResolvers 의 boolean 값(default = true) 에 의해서 viewReoslvers 들을 찾는다. 그리고 만약에 this.viewResolvers 가 null 이면 getDefaultStrageies() default 전략으로 viewResolver를 찾는다.
아래는 DispacherServlet.properties 에 정의되어 있는 기본전략이다.
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
여기에서 ViewSolver 의 기본 전략은 InternalResourceViewResovler 이다
다양한 DispatcherServlet 전략들
MultipartResolver
- 파일 업로드 요청 처리에 필요한 인터페이스
 - HttpServletRequest를 MultipartHttpServletRequest로 변환해주어 요청이 담고 있는 File을 꺼낼 수 있는 API 제공.
 
LocaleResolver
- 클라이언트의 위치(Locale) 정보를 파악하는 인터페이스
 - 기본 전략은 요청의 accept-language를 보고 판단.
 
ThemeResolver
- 애플리케이션에 설정된 테마를 파악하고 변경할 수 있는 인터페이스
 - 참고: https://memorynotfound.com/spring-mvc-theme-switcher-example/
 
HandlerMapping
- 요청을 처리할 핸들러를 찾는 인터페이스
 
HandlerAdapter
- HandlerMapping이 찾아낸 “핸들러”를 처리하는 인터페이스
 
HandlerExceptionResolver
- 요청 처리 중에 발생한 에러 처리하는 인터페이스
 
RequestToViewNameTranslator
- 핸들러에서 뷰 이름을 명시적으로 리턴하지 않은 경우, 요청을 기반으로 뷰 이름을 판단하는 인터페이스
 
		@GetMapping("/sample")
    public String sample() {
        return "sample";
    }
		//아무것도 리턴을 void로 해도, /sample 요청에 의해서 viewName으로 바꿔준다.
		@GetMapping("/sample")
    public void sample() {}
ViewResolver
- 뷰 이름(string)에 해당하는 뷰를 찾아내는 인터페이스
 
FlashMapManager
- 폼정보를 submit하고 POST 요청을 했을 때 -> GET 요청으로 화면을 리다이렉트 시키는 목적 여기에서 브라우저 화면을 refresh 했을때, 다시 form 정보로 보여지지 않게 하기 위함 !!
 
📚 Related Posts
- Spring WebFlux 테스트 방법
 - Spring과 MongoDB 연동 실전 가이드
 - SpringBoot, MongoDB 시작하기
 - Spring Boot 서버 타임존 설정 방법
 - SpringBoot CommandLineRunner, ApplicationRunner 초기화 방법
 - Jackson, LocalDateTime Serialization, Deserialization 이슈
 - Spring Boot, Dockerfile로 이미지 생성, 배포하기
 - SpringBoot RabbitMQ 연동하기
 - Junit5 정리
 - Spring Sentry(에러 트래킹 서비스) 적용하기
 - [Spring] 빈 주입하는 방법 && Best Practice
 - Thymeleaf 실무에서 자주 사용하는 것들
 - Thymeleaf Collection 정보 화면에 렌더링하기
 - Spring, JPA를 이용한 REST API 만들기
 - [Spring] MultipartFile을 이용한 파일 업로드
 - [Spring] 모델 검증(validation)
 - [Spring]HandlerMethodArgumentResolver 인터페이스
 - [Spring] DispatcherServlet에 대해서 알아보자
 - [Spring] MVC 만들어 보기
 - [Spring] 메세지 컨버터
 - [Spring] MVC 살펴보기
 - [Spring] @ConfigurationProperties를 이용해서 properties값들을 클래스로 관리하기
 - [Spring] Profile 설정하기
 - [Spring] SpringApplication를 통한 코딩
 - [Spring Boot] 스프링 부트 3가지 특징
 - [Spring] @SpringBootAppllication 어노테이션에 대한 고찰
 - [Spring] bean circular dependencies (빈 순환 참조)
 - [Spring]Bean에 대해서 알아보자
 - SpringBoot, JPA, H2를 이용한 간단한API 작성
 - [Spring] Spring Data Common 프로젝트 살펴보기