일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- lombok
- java
- synchronized
- Spring
- 일급 컬렉션
- 일급 객체
- builder
- Volatile
- spring security
- OAuth 2.0
- Google OAuth
- Dependency Injection
- nestjs
- factory
- middleware
- Today
- Total
HJW's IT Blog
IoC Container 과 Bean에 대한 정리 본문
IoC 란?
Inversion of Control(제어의 역전)
은 SW 엔지니어링에서 사용되는 원칙으로, 객체 혹은 프로그램의 일부에 대한 제어권을 컨테이너로 이전하는 개념이다.
전통적인 프로그래밍의 경우, 개발자가 작성한 코드가 라이브러리를 호출하는 구조이다. 하지만 IoC 를 사용할 경우, 프레임워크가 개발자의 코드를 호출하도록 한다.
우리는 왜 IoC 를 사용하는지에 집중해야 한다. IoC를 통한 장점은 다음과 같다.
- 작업 실행과 구현의 분리 : 특정 작업을 수행하는 로직과, 해당 작업을 구현하는 방식을 분리할 수 있다.
- 구현 간 전환의 용이성 : 서로 다른 구현체간 전환이 쉽다
- 프로그램의 모듈화 향상 : 각 구성 요소가 독립적으로 모듈화 된다.
- 테스트 용이성 증가
DI 란?
Dependency Injection
은 다른 포스팅에서 자세하게 다루었으니 간략하게 짚고 넘어가겠다.
DI 에선, 객체간의 연결을 객체 스스로가 아닌 assembler
가 수행하는 패턴이다. 이를 통해 객체는 직접 의존성을 생성하지 않고 외부에서 주입받을 수 있다.
public class Store {
private Item item;
public Store() {
item = new ItemImpl1();
}
}
위 코드는 전통적인 프로그래밍 방식에서 객체 의존성을 설정하는 방식이다. Store
클래스 내부에서 Item
인터페이스의 구현체를 직접 인스턴스화 하고 있다. 이럴 경우, 강한 결합, 다른 구현체로의 전환 제한, 모킹의 어려움 등의 단점이 있다.
위 코드를 DI 를 사용한 코드로 바꿔보면 다음과 같다.
public class Store {
private Item item;
public Store(Item item) {
this.item = item;
}
}
이 방식에서 Store 클래스는 특정 구현체에 의존하지 않고, 생성자를 통해 의존성을 전달받게 된다.
스프링 프레임워크는 다양한 ApplicationContext
구현체를 제공하며, 이를 통해 애플리케이션 유형에 따라 IoC 컨테이너를 구성할 수 있다:
AnnotationConfigApplicationContext
: 자바 기반 설정을 사용하는 독립형 애플리케이션.ClassPathXmlApplicationContext
: XML 파일이 클래스 경로에 위치한 경우 사용.FileSystemXmlApplicationContext
: XML 파일이 파일 시스템에 위치한 경우 사용.WebApplicationContext
: 웹 애플리케이션에서 사용.
IoC Container
Spring 의 IoC 컨테이너의 대표는 ApplicaionContext
와 BeanFactory
가 있다. Bean 의 인스턴스화, 설정 및 조립, Bean 의 생명 주기 관리 등의 역할을 한다. ApplicationContext 는 EagerLoading, 즉, 어플리케이션이 시작할 때, 모든 싱글톤 Bean 을 초기화 한다.
Spring 의 IoC 컨테이너는 Spring application 시작시 자동으로 시작된다
IoC Container 의 동작 과정
- 설정 정보 로드: ApplicationContext를 생성하며 설정 정보(XML, 애노테이션, Java 코드 등)를 로드한다. 이 설정 정보에는 Bean 정의와 의존 관계가 포함된다.
- BeanDefinition 생성 및 등록: 설정 정보를 기반으로 Bean 메타데이터(
BeanDefinition
)를 생성하고BeanDefinitionRegistry
에 등록. - BeanFactoryPostProcessor 실행:
BeanDefinition
을 조작하거나 추가할 수 있는 후처리기가 실행. - Bean 인스턴스화 및 의존성 주입: 등록된
BeanDefinition
을 기반으로 Bean 객체가 생성되고 의존성이 주입. - BeanPostProcessor 실행: 생성된 Bean 객체에 대해 초기화 전후에 추가 작업이 실행.
- 초기화 및 사용 준비: 모든 처리가 완료되면 Bean이 초기화되고,
getBean()
메소드를 통해 사용할 준비. - Bean 소멸 및 정리: 컨텍스트 종료 시 소멸 콜백 메서드가 호출되고 리소스가 정리
sequenceDiagram
participant Client
participant ApplicationContext
participant BeanDefinitionRegistry
participant BeanFactoryPostProcessor
participant BeanFactory
participant BeanPostProcessor
participant Bean
Client->>ApplicationContext: 컨텍스트 생성 요청
rect rgb(240, 240, 240)
Note right of ApplicationContext: 1단계: 설정 정보 로드
ApplicationContext->>ApplicationContext: 설정 정보 로드<br/>(XML/Annotation/Java Config)
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 2단계: BeanDefinition 처리
ApplicationContext->>BeanDefinitionRegistry: BeanDefinition 생성
Note over BeanDefinitionRegistry: Bean 메타데이터 생성<br/>- Bean 클래스 정보<br/>- 의존성 정보<br/>- 스코프/속성
BeanDefinitionRegistry-->>ApplicationContext: BeanDefinition 등록 완료
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 3단계: BeanFactoryPostProcessor
ApplicationContext->>BeanFactoryPostProcessor: 후처리기 실행
Note over BeanFactoryPostProcessor: BeanDefinition 조작/추가<br/>- PropertyPlaceholderConfigurer<br/>- CustomScopeConfigurer
BeanFactoryPostProcessor-->>ApplicationContext: BeanDefinition 후처리 완료
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 4단계: Bean 생성 및 의존성 주입
ApplicationContext->>BeanFactory: Bean 생성 요청
BeanFactory->>Bean: 인스턴스 생성
Note over Bean: 생성자 호출
BeanFactory->>Bean: 의존성 주입
Note over Bean: - @Autowired<br/>- @Value<br/>- setter 주입
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 5단계: BeanPostProcessor
BeanFactory->>BeanPostProcessor: 전처리 (postProcessBeforeInitialization)
BeanPostProcessor->>Bean: Bean 전처리 적용
Note over Bean: AOP 프록시 생성 등
BeanFactory->>Bean: 초기화 메서드 호출
Note over Bean: - @PostConstruct<br/>- InitializingBean<br/>- init-method
BeanFactory->>BeanPostProcessor: 후처리 (postProcessAfterInitialization)
BeanPostProcessor->>Bean: Bean 후처리 적용
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 6단계: 초기화 완료
BeanFactory-->>ApplicationContext: Bean 준비 완료
ApplicationContext-->>Client: getBean() 사용 가능
end
rect rgb(240, 240, 240)
Note right of ApplicationContext: 7단계: 소멸 단계
Client->>ApplicationContext: 컨텍스트 종료 요청
ApplicationContext->>Bean: 소멸 메서드 호출
Note over Bean: - @PreDestroy<br/>- DisposableBean<br/>- destroy-method
end
Bean Factory 와 ApplicationContext
BeanFactory 는 Spring 에서 제공하는 최상위의 기본 컨테이너이다. 두가지 컨테이너 모두 bean 의 관리와 DI를 수행하지만, ApplicationContext의 경우, BeanFactory 를 확장한 더욱 강력한 기능을 제공한다. 그렇기에 메모리 사용량이 중요한 경우가 아니면 ApplicationContext의 사용이 권장된다.
BeanFactory와 ApplicationContext의 차이점
특징 | BeanFactory | ApplicationContext |
---|---|---|
초기화 시점 | Lazy Loading (요청 시 Bean 초기화) | Eager Loading (애플리케이션 시작 시 Bean 초기화) |
애플리케이션 범위 | 최소한의 Bean 생성 및 관리 기능 제공 | Bean 관리 외에도 추가 기능 제공 |
국제화 지원(i18n) | 지원하지 않음 | 지원 (MessageSource 인터페이스 사용) |
이벤트 발행/리스닝 | 지원하지 않음 | 지원 (ApplicationEventPublisher 사용) |
AOP 통합 | 직접 구현 필요 | AOP 기능 통합 제공 |
웹 통합 | 지원하지 않음 | WebApplicationContext 를 통해 웹 애플리케이션 통합 |
사용 사례 | 경량 애플리케이션, 제한된 환경 | 대부분의 Spring 애플리케이션 |
구현체 | XmlBeanFactory (Spring 3.1부터 비추천됨) |
다양한 구현체 (ClassPathXml, AnnotationConfig 등) |
Servlet Container 와 IoC container 의 관계
어플리케이션이 초기화되며, Servlet container는 웹 어플이 배포될때, annotation 기반 설정을 통해 servlet을 로드하고 초기화 한다. Spring 의 경우, DispatcherServlet
이 주요 서블릿으로 등록된다. DispatcherServlet
이 초기화 되는 과정에서 내부적으로 IoC Container를 생성하여 필요한 Bean들을 로드한다.
클라이언트로부터 HTTP 요청이 들어오면, Servlet Container 는 URL mapping 에 따라 해당 요청을 Dispatcher Servlet 에 전달하는데, DispatcherServlet 은 IoC Container 로 부터 필요한 Bean 을 주입받아 요청을 처리한다.
Servlet Container 는 웹 계층에서의 프로토콜 처리, thread 관리, 보안 등의 infrastructure를 제공하는 반면, IoC container는 어플리케이션 로직 계층에서 객체 생성과 의존성 관리를 담당한다. 또한 Servlet container 의 경우, servlet 의 생명주기를 관리하고, DispatcherServlet 은 IoC container 의 초기화 및 소멸을 책임진다.
Bean
Spring Boot 의 Bean
은 어플리케이션 컨텍스트에서 관리되는 객체를 의미한다. Bean
은 어플리케이션 전반에 걸쳐 사용할 객체의 생성, 의존성 관리, IoC 및 DI 를 통해 효율적으로 어플리케이션의 구성 요소간 관계를 설정한다.
공식 문서의 정의는 다음과 같다.
스프링 IoC 컨테이너에 의해 관리되는 어플리케이션의 뼈대 객체들을 Bean 이라 부른다.
Spring 에서 Bean 들은 @Component
, @Service
, @Repository
등의 어노테이션을 통해 구성되며, 이들의 생명주기는 IoC Container 에 의해 관리된다. 즉, 개발자는 해당 객체가 Bean 임을 명시만 해주면, 나머지는 container 가 알아서 처리하는 것이다.
Bean Scope
Bean Scope는 Bean 이 존재하는 범위를 의미한다. Bean 의 생성 방식, lifecycle, 얼마나 오래 유지되고, 어떻게 공유되는지 등을 정의할 수 있다. 다음은 주요 Bean Scope 의 종류이다.
- Singleton : 기본 스코프이며, application context 당 하나의 인스턴스만 생성된다. 모든 요청에서 동일한 Bean instance 를 공유한다.
- Prototype : 상태를 가지는 Bean 에서 자주 사용되며, Bean 을 요청할 때 마다 새로운 인스턴스를 생성한다.
- Request : HTTP 요청마다 하나의 Bean instance 를 생성한다
- Session : HTTP session 마다 하나의 Bean instance 를 생성한다
@Scope("prototype")
과 같은 annotation 을통해 scope 를 지정할 수 있다.
'SPRING' 카테고리의 다른 글
Spring Bean 과 의존관계 설정 두가지 방법 (0) | 2024.11.25 |
---|---|
Spring 웹 개발 기초 (1) | 2024.11.25 |
서블릿과 Spring DispatcherServlet: 웹 애플리케이션의 핵심 이해하기 (1) | 2024.11.18 |
[SPRING BOOT] MVC Pattern (0) | 2024.05.28 |
[SPRING BOOT] IOC, DC, BEAN 에 대해 (0) | 2024.05.28 |