스프링 컨테이너

MinHo·2024년 4월 16일

Spring

목록 보기
4/12
post-thumbnail

1. 스프링 컨테이너 란 ?

스프링 컨테이너

스프링 어플리케이션에서 객체 생성과 관계 설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당한다. 또한 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있기 때문에 IoC(Inversion Of Control) 컨테이너 라고 부르기도 한다. 즉, 스프링 어플리케이션을 대부분의 동작을 스프링 컨테이너가 총괄 하게 된다.

※ 참고로 이번 포스팅에서는 IoC 가 무엇이고 DI 가 무엇인지에 대해서는 이번 장에서는 자세히 다루지 않는다.

스프링에서는 스프링 컨테이너를 다른말로 빈 팩토리 혹은 어플리케이션 컨텍스트 라고도 부르며 각각 이 기능을 대표하는 BeanFactory, ApplicationContext 는 인터페이스도 스프링에 정의 되어있다.

사실 이 둘의 관계도를 살펴보면

관계도를 통해 알 수 있는것은 ApplicationContextBeanFactory 를 상속 받고 있는 다는 것이며 다른 인터페이스들 (MessageSource, EnvironmentCapable, ApplicationEventPublisher, ResourcePatternResolver) 를 상속 받음으로써 더 다양한 기능들을 가지고 있음을 알 수 있다.

BeanFactory

  • 스프링 컨테이너의 최상위 인터페이스
  • 스프링 빈을 관리하고 조회하는 역할을 담당한다.

ApplicationContext

  • BeanFacotory 의 모든 기능을 상속받아서 제공한다.
  • 어플리케이션을 개발할 때 빈을 관리하고 조회하는 기능 외에 필요한 수 많은 부가기능들을 제공해준다.
    (메시지소스, 환경변수, 애플리케이션 이벤트, 리소스 조회,,)

그래서 실제로 스프링 컨테이너 또는 IoC 컨테이너라고 말하는 것은 바로 이 ApplicationContext 인터페이스를 구현한 구현체 오브젝트를 말하는것이다. 스프링 어플리케이션은 최소한 하나 이상의 IoC 컨테이너를 가지고 있게 된다.

2. 스프링 컨테이너가 어플리케이션을 만드는 방법

우선, 애플리케이션을 만들기전에 먼저 IoC 컨테이너를 생성하려면 어떻게 해야할까?

간단하다.

ApplicationContext ac = new AnnotaitionConfigApplicationContext();

이렇게 ApplicationContext 의 구현체를 생성해주면 끝이다. 그러면 이제 어플리케이션을 띄울 수 있는것일까?

대답은 "NO!"

현재 의존관계를 파악할 수 있게 해주는 설정 정보도 없으며, 어플리케이션이 구동 되기 위한 핵심 코드도 전혀 없기 때문이다 즉, 컨테이너가 컨테이너 답게 일을 하려면 언급했듯이 준비물이 필요한데 바로 POJO 객체설정 메타 정보 이다.

POJO 클래스

애플리케이션의 핵심 코드를 담고 있는 순수 자바 객체로 특정 기술과 스펙에서 독립적 이여야하며 의존관계를 맺고 있는 다른 POJO 객체와 느슨한 결합 을 갖도록 만들어야한다.

쉽게 말해, 우리가 늘 사용하던 @Service, @Controller, @Repository 가 달려있던 자바 클래스들이 전부 POJO 클래스인셈이다. 뿐만 아니라 직접 AppConfig 파일에 @Bean 으로 등록해주던 이 클래스들도 마찬가지로 POJO 클래스인셈이다.


설정 메타정보 (feat. BeanDefinition)

IoC 컨테이너가 관리하는 객체를 우린 Bean 이라고 부른다. 그렇다면 이 Bean 들을 관리하기 위해서는 당연히 이들에 대한 메타정보가 필요로 하다.

우리는 Bean 들의 설정 정보들을 다양한 방법으로 작성 할 수 있는데

대표적으로,

  • Config 자바 파일을 작성 하는 방법
  • 자동 컴포넌트 스캔을 활용하는 방법
  • XML 설정 정보 파일을 작성하는 방법 등이 있다.

그러면 스프링은 우리가 작성한 설정 정보 파일들을 토대로 BeanDefinition 타입의 객체를 생성해내고 이 BeanDefinition 에는 Bean 객체들의 메타 정보가 담겨지게 되는것이다.

BeanDefinition 인터페이스로 정의되는 메타 정보들

  • 빈아이디, 이름, 별칭 : 빈을 구분해주는 식별자
  • 클래스 또는 클래스 이름 : POJO 클래스 정보
  • 스코프 :
  • 프로퍼티 값 또는 참조
  • 생성자 파라미터 값
  • 지연 로딩 여부, 우선 빈 여부, autowired, 부모 빈 정보, 빈 팩토리 이름
    ,,,

이때 설정 파일로부터 정보들을 추출하고 읽어들이는 녀석이 바로 BeanDefinitionReader 이다. 사실 설정 정보 파일이 XML이든 어노테이션이든 자바이든 상관이 없다. 그 파일을 읽어들일 수 있는 리더만 존재한다면 포맷과 구조에 상관없이 설정정보 파일로 사용 할 수 있다.

구조도

결국 스프링 어플리케이션이란 POJO 클래스와 설정 메타정보를 이용해 IoC 컨테이너가 만들어주는 오브젝트의 조합 인 셈이다.

3. IoC 컨테이너의 종류

StaticApplicationContext

테스트 목적으로 코드를 통해 빈을 등록하고 컨테이너가 어떻게 동작하는지 확인하고 학습 할 때 사용하는 어플리케이션 컨텍스트이며 실전에서 사용되지도 않고 해서도 안 된다. 스프링의 웹 관련 기능을 공부하고 학습 테스트로 검증해보고 싶을 때 유용하게 쓸 수 있다.

외부의 리소스를 통해 설정 정보를 주입받는게 아닌 자바 객체로 표현되는 순수한 메타 정보만을 사용한다.

GenericApplicationContext

가장 일반적인 애플리케이션 컨텍스트의 구현 클래스이다. 실전에서 사용 될 수 있는 모든 기능을 갖추고 있는 애플리케이션 컨텍스트이며 XML 파일과 같은 외부의 리소스에 있는 빈 설정 메타정보를 리더를 통해 읽어들여서 메타정보로 전환해서 사용한다. 물론 XML 뿐만 아니라 다른 포맷의 리소스도 사용 할 수 있다.

WebApplicationContext

사실 우리가 제일 주목해야하는 녀석은 바로 이 녀석이다. WebApplicationContext 는 스프링 애플리케이션에서 가장 많이 사용되는 애플리케이션 컨텍스트이며 ApplicationContext 인터페이스를 확장한 인터페이스로 웹 환경에서 사용할 때 필요한 기능이 추가된 컨텍스트 이다.

Xml 파일 을 사용한다면 XmlWebApplicationContext 구현체를 사용하게 되며
자바 혹은 어노테이션 기반 의 설정 정보일 경우 AnnotationConfigWebApplicationContext 구현체를 사용하게된다.

4. 정리

우리는 지금까지 쭈욱 스프링 컨테이너가 무엇인지? 무얼 하는지? 어플리케이션을 어떻게 실행 시키는지 등을 간략하게 살펴보았다.

이제 한번 AnnotationConfigWebApplicationContext 를 예시로 전체적인 흐름을 복습해보자!

  1. 먼저 어플리케이션에 필요한 핵심 코드를 담고있는 POJO 객체, 그리고 객체간의 연관관계 및 각종 메타 정보를 담고 있는 설정 파일 을 준비해놓는다.

  2. 어플리케이션 컨텍스트는 BeanDefinitionReader 를 통해서 설정 파일로 부터 메타정보들을 추출 한다음, BeanDefinition 객체를 생성한다.

  3. BeanDefinition 을 통해 POJO 간의 연관관계를 전부 설정하여 Bean 객체를 생성해준다.

  4. 생성된 Bean 객체는 Map 자료구조 형태의 저장소에 이름과 함께 저장이 된다.

이렇게 되면 스프링 컨테이너는 본인의 할일을 전부 마쳤다.

이후로는 이제 클라이언트로부터 요청이 들어오게 될 경우 먼저 디스패처 서블릿이 요청을 전달 받게 되고, 그 다음 어플리케이션 컨텍스트에 저장되어있는 필요한 Bean 들을 조회하여 해당 Bean 의 메서드를 호출 하는 식으로 흘러가게 될 것이다.

📚 참고 자료

본 포스팅은
김영한 스프링 핵심 원리 - 기본편

토비의 스프링 3.1

를 참고하여 작성하였습니다.

profile
Keep going

0개의 댓글