본문 바로가기

Spring/Spring MVC

[Spring] [SpringMVC] 스프링 설정 파일 분리하기 with ContextLoadListener, DispatcherServlet

설정의 분리

Spring 설정 파일을 프리젠테이션 레이어(컨트롤러 레이어)쪽과 나머지를 분리할 수 있습니다.

분리하는 이유는, 프레젠테이션 레이어 / 서비스 & 레포지토리 레이어를 분리하면 장점이 많기 때문에 설정 파일 자체도 아예 분리하여 작성하는 것입니다.

 

결론적으로, web.xml 파일에서 프리젠테이션 레이어에 대한 스프링 설정은 DispatcherServlet이 읽도록 하고, 그 외의 설정은 ContextLoaderListener를 통해서 읽도록 합니다.

 

ContextLoaderListener를 활용하는 이유

DispatcherServlet을 경우에 따라서 2개 이상 설정할 수 있는데(사실 이런 경우는 별로 없음) 이 경우에는 각각의 DispathcerServlet의 ApplicationContext가 각각 독립적이기 때문에 각각의 설정 파일에서 생성한 빈을 서로 사용할 수 없습니다.

(조금 더 자세히 말하자면, DispatcherServlet은 init되는 시점에 Application Context(스프링 컨테이너)를 생성하는데 여기서 사용되는 Application Context는 해당 DispatcherServlet에서만 사용할 수 있다.)

 

하지만, 위의 경우와 같이 동시에 필요한 빈은 ContextLoaderListener를 사용함으로써 공통으로 사용하게 할 수 있습니다.

 

아래의 그림에서처럼, ContextLoaderListener와 DispatcherServlet은 각각 ApplicationContext를 생성하는데, ContextLoaderListener가 생성하는 ApplicationContext가 root컨텍스트가 되고 DispatcherServlet이 생성한 인스턴스는 root컨텍스트를 부모로 하는 자식 컨텍스트가 됩니다. 자식 컨텍스트들은 root컨텍스트의 설정 빈을 사용할 수 있기 때문에, 이를 이용해 동시에 필요한 빈을 ContextLoaderListener가 만들어낸 context에 등록하면 됩니다.

 

 

 

실제로 설정 파일을 분리했을 때( project : guestboook-upgrade ) 

  1. 자바 config 파일 분리해서 작성하기
    • 컨트롤러 레이어 : WebMvcContextConfiguration
    • 비즈니스 로직 들어가있는 레이어 : ApplicationConfig, DBConfig
  2. web.xml에 서블릿과 설정 파일 연결하기 (어떤 서블릿이 어떤 설정 파일을 읽어들일 건지 정의해두기)
    1. DispatcherServlet은 WebMvcContextConfiguration 사용하도록 설정
    2. <listener-class>에 lister로, ContextLoaderListener 등록하기
      • ContextLoaderListener가 실행된다는 뜻은, 컨테이너가 만들어진다는 뜻인데, 컨테이너가 만들어질 때 <context-param>을 참고해서 만들어진다
    3. <context-param>에 ApplicationConfig 등록하기
      • 참고 : <context-param>
        • 같은 Web Application에 있는 Servlet들이 같이 공유해서 사용할 수 있는 전역변수
        • param-name : context-param의 이름
        • param-value : context-value의 값
    4. <context-param>에  AnnotationConfigWebApplicationContext 등록하기
      • 스프링 컨테이너(context)를 만들 때, annotation기반 context로 만든다는 뜻이다
<!--
  ContextLoaderListener 실행 시, context-param에 있는 부분을 참고하여 실행한다!
  1. AnnotationConfigWebApplicationContext를 이용한다
  2. ApplicationConfig를 설정 파일로 사용한다
  -->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>org.example.guestbookupgrade.config.ApplicationConfig
    </param-value>
  </context-param>
  <!--ContextLoaderListener : 서버가 실행될 때 실행되는 파일-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

 

설정 분리 시, 주의할 점 (실제로 이걸로 에러 났었음)

설정 분리하면서, 각 config 파일에 @Configuration을 붙이고, @ComponentScan을 붙인다.

 

중요한 것이, ApplicationConfig의 @ComponentScan의 basePackages에 "WebMvcContextConfiguration이 들어가있는 패키지"가 포함되면 안된다!!

설정을 분리하고, ComponentScan도 따로 진행하기 때문에, 서로가 서로의 configuration 파일을 포함하지 않도록 해야한다!

 

(WebMvcContextConfiguration은 DispatcherServlet이 만들어내는 스프링 컨텍스트에 대한 설정이고,

ApplicationConfig은 ContextLoadListener가 만들어내는 스프링 컨텍스트에 대한 설정이기 때문에, 각자의 componentscan의 범위가 겹치면 안되는 것이다)



ComponentScan의 범위가 서로서로 침범하지 않도록 하기 위해, controller, service, dao와 같이 더 구체적인 패키지로 지정해주어 설정의 분리를 완벽하게 해주어야 한다.

 

 

[참고 블로그]

https://yoons-development-space.tistory.com/59

 

[Spring] [Test] [Error] 1. @ContextConfiguration에 들어갈 파라미터는? 2. @ComponentScan 범위의 중요성 / 에러내

@ContextConfiguration을 붙여주는 과정에서 에러가 생겼다. 9월 24, 2022 11:45:31 오후 org.springframework.context.support.AbstractApplicationContext refresh 경고: Exception encountered during context..

yoons-development-space.tistory.com