본문 바로가기
Spring

[Spring] ServletContainer? DI Container? Bean? POJO?

by Real Iron 2019. 2. 18.

ServletContainer? DI Container? Bean? POJO?

Spring·2016.07.29 09:22


매주 월/목요일 저녁마다 박재성(a.k.a 자바지기)님의 Java 강의를 수강중이다. 

(현재 1기인데 다음 2기가 시작되면 꼭꼭 듣길 추천한다. 참고)

매 시간마다 즐거운 깨달음의 연속이지만 특히나 어제 (2016년 7월 29일)의 경우 그동안 답답했던 내용들이 속시원하게 해결이 되어 기쁜 마음에 아침부터 정리를 하게 되었다.


(풀렸다!!)


SpringFramework는 웹 프레임워크가 아니다. 

Java기반의 프레임워크로서 여러 모듈로 구성되어 있는데, 이중 웹 어플리케이션을 만들고자 등장한게 SpringMVC 모듈이다

SpringMVC를 사용중 이라면 자주 만나는 용어가 Servlet Container(서블릿 컨테이너) 와 DI Container (DI 컨테이너 혹은 Spring Container, IoC Container라고도 불린다 여기선 DI Container로 통일해서 사용하겠다) 이다. 

둘다 컨테이너라는 이름을 사용중 인만큼 무언가를 저장한다는건 알수 있지만 명확하게 구분하기는 어려웠다.

아래의 그림과 함께 둘의 차이를 알아보겠다. 




 (직접 그린거라 색감이 좀...)


Servlet Container는 Servlet 저장소라고 봐도 무방하다. Java로 웹을 개발하기 위해 여러 Servlet들이 필요하게 되는데, 이러한 Servlet들의 Life Cycle (생명주기) 관리, 멀티쓰레드 지원 등을 하고 있는 것이 Servlet Container이다. 우리가 알고 있는 대표적인 Servlet Container가 Tomcat 이다.


Spring MVC 역시 Servlet Container가 관리하고 있는 Servlet이다. 

그래서 Servlet 없이 Spring MVC만 있으면 된다고 하는것은 비지니스 로직을 Spring을 통해 처리하겠다는것이지 Servlet이 필요없다는 얘기가 아니다. 


Spring MVC로의 모든 요청과 응답은 DispatcherServlet이 관리하고 있다.

URL요청이 오면 이를 가로채서 HandlerMapping (@RequestMapping으로 봐도 무방) 에게 해당 요청을 처리할 수 있는 Controller를 찾아내어 요청을 Controller에게 보내고 결과값을 리턴해준다. 

자세한 설명은 다음시간에 좀더 하고 아래 그림을 DispatcherServlet의 흐름을 보면 좋을것 같다!


(전자정부 프레임워크라 쓰고, Spring Framework라고 읽는다..) 



Bean(빈)이란 Spring이 관리하는 인스턴스이다. 

즉, 개발자가 직접 인스턴스를 생성하고 호출, 삭제하는 것이 아니라 항상 Spring이 제공하는 Container를 통해서 관리되는 인스턴스를 우린 Bean이라고 부른다.


아래의 그림을 참고하자.

(공식사이트 참고)


POJO와 설정(Configuration Metadata)을 Spring이 제공하는 Container(DI Container == IoC Container)에 주입시키면 Bean으로 등록되고 사용이 가능하다는 얘기이다.

(Spring Framework를 사용한다고 해서 본인이 만든 모든 Class들이 Bean으로 자동 등록되는 것은 아니다)


Bean은 기본적으로 싱글톤의 스코프를 가진다. 즉, Bean으로 지정된 Class는 Container에서 1개의 인스턴스로만 존재 할 수 있다. 다만 싱글톤 스코프외에도 다양한 스코프를 직접 설정해서 지정할 수도 있다. (좀더 자세한 내용은 여기를 참고하자.)


여기서 설정은 흔히 사용하는 XML이나 어노테이션이라고 보면 되는데, 그렇다면 POJO란 무엇인가?


POJO는 Plain Old Java Object의 약자인데 그 어느 곳에도 종속되지 않은 (즉, 상속받지도, 구현하지도 않은 독립적인) Java Class를 말한다.

다른 곳에 종속되지 않는 다는 것은 해당 클래스를 사용하기 위해 다른 프레임워크 같은 외부 환경이 필요하고, 해당 환경이 특정 인터페이스를 구현할 것을 강요하는 것 같은 제약에서 자유롭다는 것을 뜻합니다.


이는 2.x 버전 이전의 EJB와 대비해서 강조되던 내용이고, 스프링을 '경량 프레임워크'라고 부르는 것과도 같은 맥락의 이야기입니다. 따라서 어플리케이션 서버 같은 외부 구동환경과 무관한 비즈니스 계층의 다른 클래스를 상속하거나 구현하더라도 'POJO'라고 부르는 데 문제가 생기는 것은 아님을 명확히 하고 싶습니다.


OKKY의 fender님 첨언!

감사합니다!


즉, Spring MVC를 걷어내도 POJO들은 정상적으로 작동이 되어야 한다는 것이다.

(여담으로 이전에 XML로 설정할때까지만 하더라도 Spring MVC를 걷어내도 개발자가 작성한 Class들은 그대로 다른 Framework에서 사용이 가능했지만 어노테이션 기반으로 가면서 더이상 POJO라고 하기엔 무리가 있다.)


Spring이 제공하는 대표적인 DI Container는 BeanFactory와 ApplicationConext가 있다.

(IntelliJ의 Show Diagram 기능을 이용하여 계층구조를 시각화 하였다.)


BeanFactory는 DI Container의 기본이 되는 인터페이스인데, Bean을 관리하는 역할을 하는 인터페이스이다.

ApplicationContext는 BeanFactory를 상속한 인터페이스로 BeanFactory의 기능외에 추가적으로 AOP와 같이 대규모 웹 프로젝트에 필요한 여러 확장기능들을 포함하고 있다. 이로인해 Spring 프로젝트의 대부분은 ApplicationContext을 통해 Bean을 관리한다. 


Spring의 Bean을 ApplicationContext가 관리하고 있기 때문에 테스트 코드 작성시 @Service나 @Repository같은 Bean들을 사용하고 싶을때는 강제로 ApplicationContext를 생성하면 된다. 아래처럼


 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //applicationContext 생성

 FileEventDao fileEventDao = (FileEventDao)ctx.getBean("fileEventDao"); //applicationContext에서 Bean 호출


이외에도 ApplicationContext의 AOP와 같은 핵심 기능들은 수업이 진행됨에 따라 하나하나 정리를 해나가겠다.


(위한 여행~)


올림픽 때문에 일정 스트레스가 너무 심했는데 그래도 마음의 위안이 온다. 

여태껏 사용법만 익혀와서 너무 갈증난 상태다보니 너무 궁금한게 많아진것 같다.

정말 잘하고 싶다. 너무너무!!