Toby 스프링3 2부 1장 IoC 컨테이너와 DI
11 Oct 2017 | 스프링 spring1장 IoC 컨테이너와 DI
1.1 IoC 컨테이너 : 빈 택토리와 애플리케이션 컨텍스트
- IoC 컨테이너 : 컨테이너가 코드 대신 오브젝트의 제어권을 가지고 있다.
- 빈 팩토리 : 오브젝트의 생성과 오브젝트 사이의 런타임 관계를 설정하는 DI 관점으로 볼때는 컨테이너를 빈 팩토리가 된다.
- 스프링 컨테이너 또는 IoC 컨테이너라고 말하는 것은 바로 ApplicationContext 인터페이스 구현한 클래스 오브젝트이다.
1.1.1 IoC 컨테이너를 이용해 애플리케이션 만들기
POJO 클래스와 클래스 간의 관계를 정의한 메타 정보를 가지고 스프링 컨테이너로 빈을 생성하게 하면 된다.
스프링 IoC컨테이너는 각 빈에 대한 정보를 담은 설정 메타정보를 읽어들인 뒤에, 이를 참고해서 빈오브젝트를 생성하고 프로퍼티나 생성자를 통해 오브젝트를 주입해주는 DI 작업을 수행한다.
POJO 클래스(Plain Old Java Object)
설정 메타정보
- BeanDefinition
- 빈 아이디, 이름, 별칭
- 클래스 또는 클래스 이름
- 스코프 : 싱글톤, 프로토타입과 같은 빈의 생성방식과 존재 범위
- 프로퍼티 값 또는 참조: DI에 사용할 프로퍼티 이름과 값 또는 참조할 빈의 이름
- 지연된 로딩의 여부, 우선 빈 여부, 자동와이어링 여부, 부모 빈 정보, 빈 팩토리 이름 등
- BeanDefinitionReader : 메타정보를 정의한 원본(xml, java등등)의 포맷과 구조, 자료의 특성에 맞게 읽어와 BeanDefinition 오브젝트로 변환해 준다.
1.2. IoC 컨테이너 종류와 사용 방법
StaticApplicationContext
- 코드를 통해 빈 메타정보를 등록하기 위해 사용
- 스프링 기능에 대한 학습 테스트에 사용
- 웹관련 기능 학습 => StaticWebApplicationContext를 사용
GenericApplicationContext
- 가장 일반적인 애플리케이션 컨텍스트의 구현 클래스
GenericXmlApplicationContext
- GenericApplicationContext + XmlBeanDefinitionReader
WebApplicationContext
보통 main과 같은 기동 역할을 맡은 빈을 사용하려면 IoC 컨테이너에 요청해서 빈 오브젝트를 가져와야 한다. IoC 컨테이너의 역할은 이렇게 초기에 빈 오브젝트를 생성하고 DI한 후에 최초로 애플리케이션을 기동할 빈 하나를 제공해주는 것이다.
하지만, 웹애플리케이션을 동작하는 방식이 근복적으로 다르다. 독립 자바 프로그램은 자바 VM에게 main()메소드를 시작 시켜달라고 할수 있다. 하지만 웹에서는 main()을 호출할 방법이 없다.
그래서 웹환경에서는 main() 메소드 대신 서블릿 컨테이너가 브라우저로부터 오는 HTTP 요청을 받아서 해당 요청에 매핑이 되어 있는 서블릿을 실행해주는 방식으로 동작 한다. 서블릿이 일종의 main() 메소드와 같은 역할을 한다.
스프링은 웹 환경에서 애플리케이션 컨텍스트를 생성하고 설정 메타정보로 초기화 해주고, 클라이언트로부터 들어오는 요청마다 적절한 빈을 찾아서 이를 실행해주는 DispatcherServlet이라는 이름의 서블릿을 제공한다. 스프링이 제공해준 서블릿을 web.xml에 등록하는 것으로 웹환경에서 스프링컨테이너가 만들어지고 애플리케이션을 실행하는 데 필요한 대부분의 준비가 끝난다.
web.xml 파일은 웹애플리케이션의 배포 설명자이다.
웹애플리케이션의 컨텍스트 구성 방법
-
서블릿 컨텍스트와 루트 애플리케이션 컨텍스트 계층구조
가장 많이 사용되는 기본구성 방법
스프링 웹기술을 사용하는 경우 웹관련 빈은 서블릿컨텍스트에 두고 나머지는 루트 애플리케이션 컨텍스트에 등록한다.
루트 컨텍스트는 모든 서블릿 레벨 컨텍스트의 부모 컨텍스트가 된다. -
루트 애플리케이션 컨텍스트 단일 구조
스프링 웹기술을 사용하지 않고 서드파티 웹 프레임워크나 서비스엔진만을 사용해서 프리젠테이션 계층을 만든다면 스프링 서블릿을 둘 필요가 없다. 이때는 루트 컨텍스트만 등록한다. -
서블릿 컨텍스트 단일구조
스프링 웹기술을 사용하면서 스프링외의 프레임워크나 서비스 엔진에서 스프링 빈을 이용할 생각이 아니라면 루트 애플리케이션 컨텍스트를 생략할 수 있다.
이때 서블릿 안에 만들어지는 애클리케이션 컨텍스트는 부모 컨텍스트를 갖지 않기 때문에 스스로 루트 컨텍스트가 된다. 하지만 웹 애플리케이션 레벨에 두는 공유가능한 루트컨텍스트와는 구분이 된다.
루트 애플리케이션 컨텍스트 등록
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
ServletContextListener 인터페이스: 웹 애플리케이션의 시작과 종료 시 발생하는 이벤트를 처리하는 리스너
웹 애플리케이션의 web.xml 파일 안에 리스너 선언을 등록
ContextLoaderListener: 웹애플리케이션이 시작할 때 자동으로 루트 애플리케이션 컨텍스트를 만들고 초기화 해준다.
Default 설정
- 애플리케이션 컨텍스트 클래스 : XmlWebApplicationContext
- XML설정파일 위치 : /WEB-INF/applicationContext.xml
- contextConfigLocation : XML설정파일 위치 지정
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/daoContext
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
- contextClass : 컨택스트 클래스 지정
<context-param>
<param-name>contextClass</param-name>
<param-value>
ort.springframework.web.context.support.AnnotationConfigApplicationContext
</param-value>
</context-param>
AnnotationConfigApplicationContext를 사용할 때는 contextConfigLocation를 반드시 선언해 주어야 한다.
서블릿 애플리케이션 컨텍스트 등록
스프링의 웹 기능을 지원하는 프론트 컨트롤러 서블릿은 DispatcherServlet이다.
서블릿의 이름을 다르게 지정하면 하나의 웹 애플리케이션에 여려개의 DispatcherServlet을 등록할 수 있다. 각 DispatcherServlet은 서블릿이 초기화 될 때 자신만의 컨텍스트를 생성하고 초기화 한다. 동시에 웹 애플리케이션 레벨에 등록된 루트 애플리케이션 컨텍스트를 찾아서 이를 자신의 부모 컨텍스트로 사용 한다.
서블릿 컨텍스트를 위한 서블릿 등록
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
- <servlet-name>
DispatcherServlet에 의해 만들어지는 애플리케이션 컨텍스트는 모두 독립적인 네임스페이스 를 만든다. 이 네임스페이스는 서블릿 단위로 만들어지는 컨텍스트를 구분하는 키가 된다. 네임스페이스는 서블릿 이름 + servlet이 된다.
네임스페이스가 중요한 이유는 DispatcherServlet이 사용할 디폴트 xml 설정파일의 위치를 네임스페이스를 이용해서 만들기 때문이다.
서블릿 컨텍스트가 사용할 디폴트 설정파일은 아래 규칙으로 만들어진다.'/WEB-INF'+서블릿네임스페이스+'.xml'
네임스페이스를 만드는 이유는 여러 개의 DispatcherServlet이 등록되더라도 각각 구분할 수 있고, 자신만의 디폴트 설정파일을 가질 수 있도록 하기 위해서이다.
- <load-on-startup>
load-on-startup은 서블릿 컨테이너가 등록한 서블릿을 언제 만들고 초기화할 지, 또 그 순서는 어떻게 되는지를 지정하는 정수 값이다. 이 항목을 생략하거나 음의 정수로 넣으면 해당 서블릿은 서블릿 컨테이너가 임의로 정한 시점에서 만들어지고 초기화된다. 반대로 0 이상의 값을 넣으면 웹 애플리케이션이 시작되는 시점에서 서블릿을 로딩하고 초기화한다. 또한 여러 개의 서블릿이 등록되어 있다면 작은 수를 가진 서블릿을 우선적으로 만들어 진다.
DispatcherServlet은 서블릿의 초기화 작업 중에 스프링 컨텍스트를 생성한다. 컨텍스트의 설정이나 환경에 문제가 있다면 컨텍스트 생성 시 대부분의 확인이 가능하다. 따라서 웹 애플리케이션이 시작되고 가능한 한 빨리 서블릿 컨텍스트의 초기화가 진행되는 것이 바람직하다. 그래야 문제를 빠르게 파악할 수 있다.
Comments