스프링의 IoC 컨테이너: BeanFactory와 ApplicationContext
스프링의 가치를 제대로 누리며 사용하려면 스프링을 제대로 공부해야 한다. 스프링이 지향하는 가치와 프로그래밍 모델을 충분히 이해하지 못하고는 제대로 활용할 수 없다.
스프링을 성공적으로 학습했는지를 확인할 수 있는 좋은 방법이 있다. 스프링을 공부하고 적용한 이후에 자신이 좀 더 나은 개발자가 되었는가 확인해보는 것이다. ... 스프링을 공부하고 적용했지만 스프링의 사용법에 조금 익숙해진 것을 빼면 더 나아진 게 없다고 느낀다면 스프링을 잘못 공부한 것일지도 모른다.
IoC와 IoC 컨테이너
스프링 애플리케이션에서는 객체 생성과 관계설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당한다. 컨테이너가 코드 대신 객체에 대한 제어권을 갖고 있다고 해서 Inversion of Control이라고 부른다. 그래서 스프링 컨테이너를 IoC 컨테이너라고도 한다.
스프링의 IoC 컨테이너: BeanFactory
스프링에선 IoC를 담당하는 컨테이너를 BeanFactory 또는 ApplicationContext라고 부르기도 한다. 객체 생성과 객체 사이의 런타임 관계를 설정하는 Dependency Injection(이하 DI) 관점으로 볼 때는 컨테이너를 BeanFactory라고 한다.
스프링의 IoC 컨테이너: ApplicationContext
그런데 스프링 컨테이너는 단순한 DI 작업보다 더 많은 일을 한다. DI를 위한 BeanFactory에 엔터프라이즈 애플리케이션을 개발하는 데 필요한 여러 가지 컨테이너 기능을 추가한 것을 ApplicationContext라고 부른다. 즉 ApplicationContext는 그 자체로 IoC와 DI를 위한 빈 팩토리이면서 그 이상의 기능을 가졌다고 보면 된다.
스프링의 IoC 컨테이너는 일반적으로 애플리케이션 컨텍스트 즉, ApplicationContext 인터페이스를 구현한 클래스의 객체를 말한다. 스프링 애플리케이션은 최소한 하나 이상의 IoC 컨테이너, 즉 애플리케이션 컨텍스트 객체를 가지고 있다.
스프링 IoC 컨테이너 만들기
IoC 컨테이너로서 동작하려면 두 가지가 필요하다. 바로 POJO 클래스와 설정 메타정보다. 먼저 각자 기능에 충실하게 독립적으로 설계된 POJO 클래스를 만들고, 결합도가 낮은 유연한 관계를 가질 수 있도록 인터페이스를 이용해 연결해준다.
이제 필요한 것은 POJO 중에 애플리케이션에서 사용할 것을 선정하고 이를 IoC 컨테이너가 제어할 수 있도록(어떻게 생성하고 어떻게 동작하게 할 것인지 정할 수 있도록) 적절한 메타정보를 만들어 제공하는 작업이다.
스프링의 설정 메타정보는 BeanDefinition 인터페이스로 표현되는 순수한 추상 정보다. 즉 애플리케이션 컨텍스트는 바로 이 BeanDefinition으로 만들어진 메타정보를 담은 객체를 사용해 IoC와 DI 작업을 수행한다. 따라서 스프링의 메타정보는 특정한 파일 포맷이나 형식에 제한되거나 종속되지 않는다. 대신 XML이든 소스코드 애노테이션이든 자바 코드이든 프로퍼티 파일이든 상관없이 BeanDefinition으로 정의되는 스프링의 설정 메타정보의 내용을 표현한 것이 있다면 무엇이든 사용 가능하다. 원본의 포맷과 구조, 자료의 특성에 맞게 읽어와 BeanDefinition 객체로 변환해주는 BeanDefinitionReader가 있으면 된다. BeanDefinitionReader도 인터페이스이다. 따라서 이를 구현한 리더를 만들기만 하면 스프링의 설정 메타정보는 어떤 형식으로든 작성할 수 있다.
스프링 애플리케이션이란 POJO 클래스와 설정 메타정보를 이용해 IoC 컨테이너가 만들어주는 객체의 조합이라고 할 수 있다.