본문 바로가기

스프링

[spring] 서블릿 구동방식_IOC컨테니너구성_이론

* WebApplicationContext

> 스프링 애플리케이션에서 가장 많이 사용되는 애플리케이션 컨텍스트. 웹 애플리케이션에서 만들어지는 IOC 컨테이너(인터페이스)

> ApplicationContext (상속) 확장 인터페이스

> XmlWebApplicationContext : XML 설정파일 사용. 주로 사용됨.(디폴트)

> AnnotaionConfigWebApplicationContext : 애노테이션 설정을 사용하는 리소스

 

* IOC컨테이너의 작동원리

> 애플리케이션 컨텍스트 별로 인자값에 설정파일을 넣거나, refesh()를 호출하면, 빈 설정 메타정보를 이용해 빈 오브젝트를 만들고 DI 작업을 수행한다.(아직은 미실행 단계)

> 이후 진정한 실행단계가 되려면, 자바 애플리케이션의 main() 메소드 처럼 어디에선가 특정 빈 오브젝트의 메소드를 호출함으로 써 애플리케이션이 동작함.

 

하지만 웹은 main() 처럼 어딘가에서 애플리케이션을 동작시킬 수 가 없다.

> 서블릿 컨테이너는 브라우저로부터 오는 HTTP 요청을 받아 해당 요청에 매핑되어 있는 서블릿을 실행해주는 방식으로 동작.(서블릿이 main 역할 수행)

1. main() 메소드 역할을 하는 서블릿을 만들고, 요청이 올 때마다 getBean()으로 필요한 빈을 가져와 정해진 메소드를 실행해주면 된다.

2. 다행히 스프링은 이런 웹 환경에서 애플리케이션 컨텍스트를 생성하고 설정 메타 정보로 초기화해주고, 클라이언트로부터 들어오는 요청마다 적절한 빈을 찾아서 이를 실행해주는 기능을 가진 DispatcherServlet이라는 이름의 서블릿을 제공한다.

3. 스프링이 제공해준 서블릿을 web.xml에 등록하는 것만으로 웹 환경에서 스프링 컨테이너가 만들어지고 애플리케이션을 실행하는데 필요한 준비는 끝이다.

 

* 웹 애플리케이션의 IOC 컨테이너 구성 방법

1. 웹 모듈(WAR) 안에 컨테이너 구성

2. 엔터프라이즈 애플리케이션 레벨에 두는 구성

 

 

1. Spring MVC(웹애플리케이션 지원(DispatcherServlet)) 하나의 서블릿으로 보면됨.

* 자바 서버 기술이 막 등장했던 초장기에는 URL당 하나의 서블릿을 만들어 각각 독립적인 기능을 담당하게 했다.

> 프론트 컨트롤러 패턴 : 몇 개의 서블릿이 중앙 집중식으로 모든 요청을 다 받아서 처리하는 방식

> 스프링 역시 프론트 컨트롤러 패턴을 사용하므로 서블릿의 숫자는 하나이거나 많아야 두셋 정도다.

 

 

1. 웹 모듈(WAR) 안에 IOC컨테이너 구성

 1) 애플리케이션의 요청을 처리하는 서블릿 안에서 IOC 컨테이너 만들어지는 방법.

 2) 웹 애플리케이션(Web app) 레벨에서 만들어지는 방법

- 스프링 애플리케이션의 진입창구 역할을 하는 프론트 컨트롤러 서블릿이 한 개 이상 등록된다면, 그만큼 전체 컨테이너 개수는 늘어난다.

> 웹 애플리케이션 레벨에 등록되는 컨테이너는 루트 웹 어플리케이션 컨텍스트라고 불린다. 이 컨텍스트는 서블릿 레벨에 등록되는 컨테이너들의 부모 컨테이너가 된다. 여기에 서블릿A와 서블릿B의 공통적인 빈을 공유해서 사용할 수 있게 된다.

> 서블릿을 2개 이상 구성하는 경우는 특별한 이유로 기존에 만들어진 서블릿 레벨의 애플리케이션 컨텍스트 설정을 그대로 유지하면서 새로운 기능이나 별도의 웹 기술을 추가하고 싶은 경우에나 사용된다.

 

프레젠테이션 계층

 

* 대부분 요청을 분산하는 경우가 없으므로 위와 같은 구조가 대부분이다.

> 그런데 왜 여러 개의 자식 컨텍스트가 없는데 왜 이렇게 계층구조로 만들까?

 - 전체 애플리케이션에서 웹기술에 의존적인 부분과 그렇지 않은 부분을 구분하기 위해서.

   : DAO, Service 계층은 스프링 기술을 사용하지만, 웹을 담당하는 프레젠테이션 계층은 스프   링 외의 기술을 사용하는 경우도 종종 있기 때문

 

여러 프레젠테이션 계층 중 모델1 등의 아키텍처로 만든 애플리케이션에서 스프링으로 만든 서비스 계층 빈을 사용하는 경우도 있다. 따라서 스프링 서블릿을 사용하는 스프링의 웹 기술 외의 웹 기술을 위한 확장성을 위한 계층형태라고 보면 된다.

> 위와 같이 프레젠테이션 계층을 분리해서 계층구조 애플리케이션 컨텍스트를 구성해두면 언제든지 간단히 웹 기술을 확장하거나 변경, 조합해서 사용할 수 있으므로 당장에는 스프링 서블릿 한가지만 존재한다 해도 이런 계층구조로 만들어두는 것이 권장된다.

* ApplicationContext 계층구조 사용시 주의사항

- 서블릿의 컨텍스트 빈은 루트 애플리케이션 컨텍스트 빈을 참조할 수 있지만 그 반대는 안 된다.

- 루트 컨텍스트에 정의된 빈은 이름이 같은 서블릿 컨텍스트의 빈이 존재하면 무시될 수도 있다.

- 하나의 컨텍스트에 정의된 AOP 설정은 다른 컨텍스트의 빈에는 영향을 미치지 않는다.

> 스프링 애플리케이션의 XML 설정파일은 보통 계층이나 성격에 따라 여러 개의 파일로 분리해서 작성하면 편리하다. 이런 경우 설정파일마다 하나씩 컨텍스트를 만들고 계층구조로 묶는 방법도 가능하겠지만, 하나의 컨텍스트가 여러 개의 설정파일을 사용하게 만들 수도 있다.

- 등록되는 빈의 개수가 많은 경우 파일 하나에 설정정보의 양이 너무 많아지면 작성하고 관리하는데 불편하다. 그래서 성격이 다르거나 관리 주체가 달라지는 경우에 파일을 여러 개로 분리하면 유용할 때가 많다.

- 파일을 계층별로 구분해두거나 자주 바뀌는 설정과 고정된 설정을 구분하는 것도 좋다.

- 때로 개발팀 혹은 개인별로 자신이 맡은 모듈의 설정을 담은 파일을 별도로 구분해서 관리하고 싶은 경우도 굳이 계층구조로 만들기 보다는 설정파일을 여러 개 등록해주면 충분하다.

 

> JSP나 스트럿츠, AJAX 엔진은 위와 같은 방법으로 루트 컨텍스트를 얻어와 어떤 빈이든 사용할 수 있다.

> ServletContext는 웹 애플리케이션마다 하나씩 만들어지는 것으로, 서블릿의 런타임 환경정보를 담고있다. HttpServletRequestHttpSession 오브젝트를 갖고 있다면 간단히 ServletContext를 가져올 수 있다.

> 스프링과 연동되서 사용할 수 있는 서드파티 웹 프레임워크는 위와 같은 방법으로 스프링 빈을 가져와 사용해야 한다.

 

* 웹 애플리케이션 컨텍스트 구성방법 3가지

1) 서블릿 컨텍스트와 루트 애플리케이션 컨텍스트 계층구조

> 서블릿 컨텍스트 : 스프링 웹 기술관련 빈들 등록

> 루트 애플리케이션 컨텍스트 : 서비스 및 DAO 등 나머지

> 다른 웹 기술 사용시 확장성 용이.

2) 루트 애플리케이션 컨텍스트 단일구조

> 스프링 웹기술 없이, Model1이나 Struts 등을 사용한다면 스프링 서블릿을 둘 이유가 없으므로 루트 애플리케이션 컨텍스트만 등록

3) 서블릿 컨텍스트 단일 구조

> 스프링 웹 기술을 사용하면서 스프링 외의 다른 기술을 사용시 루트 애플리케이션 컨텍스트 생략.

> 계층구조의 혼란을 피하고 단순한 설정 선호시 사용.

> 계층관점에서 보자면 서블릿 컨텍스트가 루트 애플리케이션 컨텍스트가 되는 것이지만, 웹 애플리케이션 레벨에 두는 공유 가능한 루트 컨텍스트와는 구별된다.

 

> 루트 웹 애플리케이션 컨텍스트를 등록하는 가장 간단한 방법

* ServeltContextListener 인터페이스

> 스프링의 ContextLoaderListener는 해당 인터페이스를 구현한 리스너

> 웹 애플리케이션의 시작과 종료시 발생하는 이벤트를 처리하는 리스너

> 웹 애플리케이션 전체에 적용 가능한 DB 연결 기능이나 로깅 같은 서비스를 만드는데 유용하게 쓰임.

* spring ContextLoaderListener

> 웹 애플리케이션이 시작될 때 루트 애플리케이션 컨텍스트를 만들어 초기화 기능.

> 웹 애플리케이션이 종료될 때 컨텍스트를 함께 종료하는 기능

> 루트 애플리케이션 컨텍스트 초기화할 때 설정파일

 - 디폴트 설정파일 : /WEB-INF/applicationContext.xml

 - 설정파일 경로 지정시 아래 스샷 참조

 

> context-param : 웹 애플리케이션 전체에 결쳐서 사용할 수 있는 초기화 파라미터(Serveltapplication 객체를 통해 파라미터를 가져올 수 있음.)

> SpringContextLoaderListener가 이용할 컨텍스트 파라미터에 contextConfigLoaction 파라미터를 넣어주면 디폴트 경로는 무시되고 파라미터로 제공된 설정파일을 사용함.

> 설정파일의 위치는 리소스 로더가 사용하는 접두어를 사용해서 표현할 수 있음(ex:classpath)

> 애플리케이션 규모가 커져서 등록해야할 빈이 많아지면 빈 설정을 여러 개의 파일로 조깨서 관리하는게 편할 수 있다.

> 계층별/기능 모듈별로 파일을 분리해서 만드는 방법도 좋다.

 

* contextClass : 자동으로 생성하는 컨텍스트 클래스는 XmlWebApplication이다. 다른 애플리케이션 컨텍스트를 지정하려면 WebApplicationContext 인터페이스를 구현한 컨텍스트를 사용해야함.

> 스프링이 제공하는 대체 컨텍스트는 AnnotaionConfigWebApplicationContext

 - 이때는 XML 파일이 아닌 클래스 또는 빈 스캐닝 패키지를 지정해야함.(추후 설명)

 

* 서블릿 애플리케이션 컨텍스트 등록

> DispatcherServlet

- 스프링의 웹 기능을 지원하는 프론트 컨트롤러 서블릿.

- web.xml에 등록해서 사용할 수 있는 평범한 서블릿.

- servlet-name을 다르게 지정해주면 하나의 웹 애플리케이션에 여러 개의 DispatcherServlet을 등록할 수도 있다. 또한, DispatcherServlet은 서블릿이 초기화 될 때 자신만의 컨텍스트를 생성하고 초기화한다. 동시에 웹 애플리케이션 레벨에 등록된 루트 애플리케이션 컨텍스트를 찾아서 이를 자신의 부모 컨텍스트로 사용한다.

 

Servlet-name 에 의해 서블릿 컨텍스트의 디폴트 설장파일이 결정된다. 이런 이유는 여러 개의 DispatcherServlet이 등록되더라도 각각 구분할 수 있고, 자신만의 디폴트 설정파일을 가질 수 있도록 하기 위해서임.

 

 

Load-on-startup 보통 1을 넣고, 다른 서블릿과 초기화 우선순위 조정시 사용함

 

서블릿이 사용하는 설정파일은 굳이 여러 개로 구분해서 분리할 필요가 없는 경우가 대부분임. 따라서 디폴트 설정파일을 사용하는 것이 간편함.

 

루트 애플리케이션을 사용하지 않고, 모든 계층의 빈을 서블릿 컨텍스트 안에 등록하는 경우에 여러 개 분리 가능.