Spring

스프링 부트 자동 설정 (AutoConfiguration.imports) 과 DispatcherServlet

HipPopoTamUs 2024. 5. 23. 17:00

SpringMVC 구조 복습을 하다가, 문득 이런 궁금증이 생겼다. 

 

디스패처 서블릿이 프론트 컨트롤러라는 중요한 역할을 하는데, 지금껏 개발한 코드들에서
눈씻고 찾아봐도 서블릿이 안보이네...흠...뭐지

요청에 맞는 컨트롤러를 찾으려면 @Controller를 인식해야하고... 인식하려면
RequestMappingHandlerMapping을 받아야하고... 받으려면 디스패처 서블릿이
HandlerMapping 목록을뒤져야하는데?!

디스패처 서블릿이 필요한데 디스패처 서블릿은 어디에서 등록되고 동작하고 있는거지?! 

 

 

결론부터 간단하게 정리하자면,  

  1. 스프링 부트의 @SpringBootApplication 어노테이션에는 @EnableAutoConfiguration 이 포함되어있다.
  2. 따라서 @SpringBootApplication이 붙은 애플리케이션을 실행하면, @EnableAutoConfiguration 이 활성화된다.
  3. 이는 클래스 패스를 스캔하여 필요한 빈들을 자동으로 등록하는 역할을 한다.
  4. 구체적으로, @EnableAutoConfiguration은 AutoConfiguration.imports 라는 파일을 로드한다.
  5. 그 파일에 나열되어 있는 자동 설정 클래스들을 활성화시킨다.
  6. 그들 중 DispatcherServletAutoConfiguration 이라는 자동 설정 클래스가 디스패처 서블릿을 자동 등록한다.

 

AutoConfiguration.imports 

경로: External Libraries > Gradle: org.springframework.boot:spring-boot-autoconfigure:3.2.5 > META-INF > spring > org.springframework.boot.autoconfigure.AutoConfiguration.imports

...
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration  //요기!
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
...

 

이 파일엔 자동 설정 클래스들의 경로가 나열되어있다.

직접 이 파일을 확인해보면 나열된 게 정말정말 많다... 새삼 스프링 프레임워크를 개발하신 분들이 대단하다고 느껴진다^^;

 

여기서 자동 설정 클래스란?

자동 설정 클래스는 @AutoConfiguration 어노테이션이 붙여져 있다.
이 어노테이션이 붙여진 클래스는 @EnableAutoConfiguration 에 의해 스캔되는 대상이며,
스프링 애플리케이션을 구성하는 데 필요한 설정을 자동으로 수행해준다.

 

DispatcherServletAutoConfiguration

다음은DispathcerServletAutoConfiguration 클래스 내부의

스태틱 클래스 DispatcherServletConfiguration 선언부를 발췌한 것이다.

protected static class DispatcherServletConfiguration {
	protected DispatcherServletConfiguration() {
    }
        
    @Bean(
        name = {"dispatcherServlet"}
    )
    public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        ...
        return dispatcherServlet;
    }

    ...
    @Bean
    @ConditionalOnBean({MultipartResolver.class})
    @ConditionalOnMissingBean(
        name = {"multipartResolver"}
    )
   ...
}
@Bean이 붙은 메소드의 반환값은 스프링 컨테이너에 의해 빈으로 등록된다.

 

dispatcherServlet() 메소드가 dispatcherServlet 객체를 반환하므로, 
이 메소드에 의해 디스패처 서블릿이 ApplicationContext (스프링 컨테이너)에 빈으로 등록되게 된다.

 

 

다음은DispathcerServletAutoConfiguration 클래스 내부의

스태틱 클래스 ' DispatcherServletConfiguration'  선언부를 발췌한 것이다.

protected static class DispatcherServletRegistrationConfiguration {
    protected DispatcherServletRegistrationConfiguration() {
    }

    @Bean(
        name = {"dispatcherServletRegistration"}
    )
    @ConditionalOnBean(
        value = {DispatcherServlet.class},
        name = {"dispatcherServlet"}
    )
    public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
        DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath());
        registration.setName("dispatcherServlet");
        registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
        ...
        return registration;
    }
}

 

dispatcherServletRegistration() 메소드는 디스패처 서블릿을 서블릿 컨테이너에 등록하는 역할을 하는

registration 객체를 반환한다. 그리고 이는 dispatcherServletRegistration 이름으로 빈에 등록된다.

 

또한 @ConditionalOnBean 이라는 어노테이션을 볼 수 있다.

이는 특정 빈이 컨테이너에 존재할 때에만 해당 빈을 생성하는 데 사용된다.

 

따라서 이 코드를 보자면, dispatcherServlet 빈이 스프링 컨테이너에 등록되고 나서

이를 서블릿 컨테이너에 등록하는 dispatcherServletRegistration 빈이 생성되는 것이다. 


 

이렇게 해서 DispatcherServlet이 개발 코드 상에 안보였던 이유와 

어떻게 자동 등록되어 사용되는 지를 알게되었다!

 

개인적인 궁금증에 스프링 부트 소스를 파헤쳐 가며 알아봐서

오래오래 기억에 남을 것 같다:)