진짜 개발자
본문 바로가기

FrameWork/Spring MVC

SpringMVC - Spring MVC 동작원리 - 2(Servlet에서 IoC Container를 사용하기)

728x90
Spring IoC Container를 ServletWeb project에 연동

이제 ServletWebApplication에 Spring을 도입하도록 하겠습니다. 기존 ServletWeb Application에서 Spring을 도입한다면 다음과 같은 것을 이용한다는 의미 입니다.

- Spring 에서 제공하는 IoC Continer를 사용.

- Spring MVC를 사용

 

 

1. Servlet에서 Spring IoC Container를 사용하기

1.1 의존성 추가

pom.xml에 SpringFramework를 사용하기 위한 의존성을 추가합니다.

 

그러면 SpringFramework를 사용하기 위해 필요한 Libraies가 자동으로 추가됩니다.

 

1.2 Web.xml

ServletContainer는 web.xml에 기술되어있는 내용을 바탕으로 ServletContainer를 초기화 하게 됩니다. 따라서 이곳에IoC Container를 사용하겠다고 기술을 해주어야합니다.

 

우선 <listener>태그가 보입니다. listener클래스 속성에는 ContextLoaderlistener 을 입력했습니다. 그 아래에는 <context-param>태그를 가진 두개의 속성이 보입니다. 각각의 param-namecontextClass, contextConfigLocation 입니다. 아래에서 각각에 대해 조금 더 상세히 설명드리겠습니다.

 

ContextLoaderListener

ContextLoaderListener는 ServletContext의 라이프사이클에 맞추어 ApplicationContext를 ServletContext에 추가/삭제 하도록 합니다.

 

ContextLoader

ContextLoaderListener가 상속받을 Class로 실질적으로 ApplicationContext를 생성하고 ServletContext에 setting하는 역할을 합니다. ContextLoad가 ApplicationContext를 ServletContext에 등록하기 위해서는 ApplicationContext Class TypeApplicationConetxt Configuration 파일이 필요합니다. 그러한 Class Type과 Configuration 파일을 ServletContext의 Parameter로부터 전달받게 되는데 그것들이 바로 아래의 두개의 태그들입니다.(contextClass, contextConfigLocation)

 

contextClass

contextClass의 경우 ContextLoader에서 생성할 IoC Container 클래스를 받아들일 Parameter Name을 의미합니다. 저희는 Annotation을 기반으로 Bean을 등록할 것이므로 Annotation을 인식할 수 있는 AnnotationConfigWebApplicationContext를 등록해주었습니다.

 

contextConfigLocation

contextConfigLocation은 말그대로 IoC Continaer의 설정 파일의 위치를 의미합니다. xml의 위치를 입력할 수도있고 개발자가 정의한 Java Class 파일을 입력할 수도 있습니다.

 

 

1.3 ContextLoaderListener 자세히

우선 Spring에서 제공하는 IoC Container를 이용하기 위해서ServletContextApplicationContext를 추가해야 합니다. 그러한 역할을 하는 것이 ContextLoaderListener입니다. 즉, ContextLoaderListenerServletContext의 라이프 사이클에 맞추어 ServletContext에 자동으로 ApplicationContext를 추가합니다.

 

위의 그림은 ContextLoaderListener Class입니다. ContextLoader를 상속받으며, ServletContextListener를 구현하고 있습니다. 앞선 포스팅에서 알아 보았듯이 ServletContextListener는 ServletContext의 라이프사이클에 변화를 감지합니다. contextInitialized()메소드에서 상속받은 ContextLoader 클래스에 존재하는initWebAppliationContext()라는 메소드를 호출 한것을 볼 수있습니다. 즉, ServletContext가 초기화 되는 시점에 WebApplicationContext를 초기화 한다는 의미인것 같습니다.

 

ClassLoader의 initWebApplicationContext()

ContextLoaderListener에서 상속받은 ContextLoader클래스의 initWebApplicationContext() 메소드를 조금 더 자세히 살펴보겠습니다. 다른 코드들은 복잡하여 일부분을 발췌한 사진입니다. servletContextWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE라는 키 값으로 WebApplicationContext를 담는 것를 볼 수 있습니다.

 

 

2. IoC Container 사용 예제

이제 위에서 설정한 IoC Container를 이용하여 Bean을 주입받아 사용해보도록 하겠습니다.

 

2.1 Servlet 생성

우선 간단히 HelloServlet을 만들어 보도록하겠습니다. HttpServlet을 상속받고 doGet메소드를 오버라이딩하여 인자로 전달되는 resp를 이용해 페이지를 만들어주면 됩니다.

 

그 후 Servlet을 맵핑합니다.

 

테스트를 해봅니다. 정상적으로 출력이 되네요.

 

2.2 Bean Configuration Class 생성

어노테이션 기반으로 빈을 등록하기 위해서는 xml설정 파일에 <context-component:scan> 태그를 추가하거나 Java Configuration 파일을 생성해야 합니다. Java Class를 이용할 것입니다.

 

AppConfig class를 생성합니다.

 

AppConfig Class의 경우에는 BeanConfiguration Class를 알리기 위한 @Configuration어노테이션과, Bean 등록을 위한 @ComponentScan어노테이션을 부여했습니다.

 

IoC Container에 사용될 Configuration file의 위치를 알려주는 contextConfigLocation parameter를 추가하고 방금 생성한 AppConfig Class의 풀경로를 입력해줍니다.

 

 

2.3 HelloService Class 생성

Bean으로 등록될 HelloService Class입니다.

 

간단히 이름을 반환하는 getName()메소드만을 작성하였고, ComponentScan에 의해 Bean Container에 등록되기 위하여 @Service어노테이션을 부여하였습니다.

 

이렇게 까지 설정을 하면 ServletContext에는 IoC Continaer가 존재할 것이고, IoC Container에는 우리가 설정한 Bean들이 들어가 있을것입니다. 따라서 IoC Container를 이용하여 Bean들을 필요에따라 꺼내어 사용할 수 있습니다.

 

 

2.4 IoC Container를 이용하여 HelloService Bean 주입하기

이제 앞서 생성한 IoC Container를 이용해 HelloService를 주입받고 사용해볼 것 입니다. 우선 IoC Container를 사용하려면 당연히 가져와야 합니다.

 

앞서 설명한 ContextLoader에서는 ContextLoaderListener에 의해 ServletContext에 개발자가 지정한 IoC Container를 ServletContext의 생명주기에 맞추어 자동으로 생성/삭제를 한다고 했습니다. 또한 ContextLoader Class에서는 실질적으로 IoC Container를 생성하고 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE라는 키값으로 ServletContext에 담는 역할을 한다고 말씀드렸습니다. 따라서 getServletContext().getAttribute("키값")으로 IoC Container를 가져올 수 있습니다. ServletContext의 getAttribute() 메소드에 의해서 반환되는 객체들은 모두 Object형태로 반환 되기 때문에 적절히 Casting해 사용해야 합니다.

 

이어서 생성된 applicationContext객체의 getBean() 메소드를 이용해 HelloService를 가져와 getName()메소드를 실행하면 끝입니다.

 

성공입니다~

 

 

요약

- 따라서 ContextLoaderListenerServletContext가 초기화 되는 시점에 ServletContextWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE라는 키 값으로 제공받은 WebApplicationContext를 담도록 요청해주는 역할을 하는것을 알 수 있습니다.

 

- ContextLoader는 실질적으로 IoC Container를 생성하고 ServletContext에 담는 역할을 합니다.