영어 원문 출처 - Spring 공식문서
그림 출처 - 인프런 김영한 [스프링 핵심원리 기본편]

The Spring Framework is divided into modules.
At the heart are the modules of the core container, including a configuration model and a dependency injection mechanism.
Beyond that, the Spring Framework provides foundational support for different application architectures.
스프링 프레임워크는 여러 모듈로 나뉘며 그 핵심은 의존성 주입 컨테이너이다.
나아가 서로다른 애플리케이션 아키텍처의 근본적인 지원을 제공한다.

Accomdate diverse perspectives.
Maintain strong backward compatibility.
Care about API design.
Set high standards for code quality.
디자인 철학을 읽으며 가장 첫번째 항목이 인상깊었다.
스프링은 설계 결정을 가능한 미룰수 있게 해준다. 예를들어 영속성 제공자(Hibernate, ...)를 코드의 변경 없이 configuration을 변경하는 것만으로도 가능하게 한다. 이는 다른 많은 인프라와 third-party API에도 동일하게 적용된다.
의존성 주입(Dependency Injection)은 객체지향 프로그래밍에서 객체 간의 의존성을 효율적으로 관리하기 위해 사용되는 디자인 패턴이다.
DI는 제어의 역전(IoC)의 한 형태로, 객체가 스스로 필요한 의존성을 직접 생성하거나 찾는 대신, 외부에서 주입받는 방식으로 동작한다. 객체의 의존성을 주입해주는 외부 컨테이너를 Ioc Container라고 한다.
객체지향의 다형성 만으로는 OCP(Open-Closed Principle) + DIP(Dependency Inversion Principle)를 지킬 수 없다. 스프링은 IoC Container를 통해 이를 지원한다. 순수하게 자바로 OCP, DIP 원칙들을 지키면서 개발을 해보면, 결국 DI 컨테이너를 만들게 된다.
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans.
A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
: Spring IoC 컨테이너가 관리하는 핵심 오브젝트를 빈이라고 한다.
빈들은 컨테이너에의해 인스턴스화되고, 조립되며, 관리된다.
빈과 그들의 의존관계는 Configuration Metadata에 반영된다.

BeanFactory - provides the configuration framework and basic functionality.
ApplicationContext - Complete superset of the BeanFactory. It adds more enterprise-specific functionality.
BeanFactory는 스프링 빈을 구성, 관리, 조회하는 기능을 제공하는 핵심적인 인터페이스이다.
ApplicationContext는 BeanFactory의 기능을 모두 상속받고, 운영환경에 적합한 부가기능들을 추가로 제공한다.
ApplicationContext를 구현한 구현체로 AnnotationConfig-, GenericXml-, 등이 존재하며 이는 각각 메타데이터를 구성하는 방식에 따라 나뉜다.

BeanFactory에는 위와 같이 빈의 이름(String)을 통해 빈 객체를 반환받는 getBean() 메서드와 빈의 생명주기를 파악하는 isSingleton(), isPrototype() 등의 메서드가 존재한다.

ApplicationContext는 BeanFactory외에도 국제화기능, 환경변수, 이벤트, 리소스 조회 등의 기능을 제공하는 다양한 인터페이스를 상속받는다.
ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.
The container gets its instructions on the components to instantiate, configure, and assemble by reading configuration metadata.The configuration metadata can be represented as annotated component classes, …
ApplicationContext는 곧 Spring IoC 컨테이너를 의미하며, Configuration metadata를 통해 빈을 관리한다. 이 메타데이터는 어노테이션 기반, Xml 기반 등 다양한 방식으로 표현 가능하다.

As the preceding diagram shows, the Spring IoC container consumes a form of configuration metadata. This configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the components in your application.
즉, 스프링 컨테이너는 Configuration Metadata와 POJO(Plain Old Java Object)를 소모하여 애플리케이션을 생산하는 주체인 것이다.
In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. In a Spring Boot scenario, the application context is implicitly bootstrapped for you based on common setup conventions!
대부분의 애플리케이션 구현 환경에서는 유저가 직접적으로 컨테이너를 생성할 필요는 없다. 특히 Spring Boot 환경에서는 내부적으로 셋업된다.

위에서 메타 데이터를 구성하는 방식이 다르다고 하였다. 그 방식이 다르더라도 모두 BeanDefinition을 만들어내는 것은 동일하다.
각각의 메타 데이터 형식이 BeanDefinition이라는 추상화를 만들어낸다. IoC 컨테이너는 이 BeanDefinition을 읽어들여 빈을 구성한다. 어떠한 메타데이터 형식이든 BeanDefinition만 구성이 가능하면 스프링 컨테이너를 동작시킬 수 있다.


