1. 서론
스프링 프레임워크의 핵심은 스프링 컨테이너와 그 안에서 관리되는 스프링 빈입니다. 이 포스팅에서는 스프링 컨테이너의 생성 과정부터 빈 조회 방법, 그리고 컨테이너가 다양한 설정 형식을 지원하는 원리인 BeanDefinition까지 자세히 알아보겠습니다.
2. 스프링 컨테이너 생성과 빈 등록 과정
2.1. 개요
스프링 컨테이너는 ApplicationContext 인터페이스를 구현한 클래스의 인스턴스입니다. 스프링 컨테이너를 생성하는 가장 일반적인 방법은 다음과 같습니다
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
Java
복사
여기서 AnnotationConfigApplicationContext는 ApplicationContext 인터페이스의 구현체로, Java 기반 설정 클래스를 사용하여 스프링 컨테이너를 생성합니다.
2.2. 스프링 컨테이너 생성 단계
1.
스프링 컨테이너 생성
•
구성 정보(AppConfig.class)를 지정하여 컨테이너 생성
2.
스프링 빈 등록
•
구성 정보를 바탕으로 빈 등록 (빈 이름은 메서드 이름 기본 사용)
3.
스프링 빈 의존관계 설정 준비
•
의존관계 주입을 위한 준비 단계
4.
스프링 빈 의존관계 설정 완료
•
설정 정보를 참고하여 의존관계 주입(DI) 완료
3. 스프링 빈 조회 방법
스프링 컨테이너에서 빈을 조회하는 다양한 방법이 있습니다
// ApplicationContext & AppConfig 설정은 선행으로 필요. 소스코드 참고
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
TypeScript
복사
3.1. 기본 조회 방법
// 빈 이름과 타입으로 조회
MemberService memberService = ac.getBean("memberService", MemberService.class);
// 타입으로만 조회
MemberService memberService = ac.getBean(MemberService.class);
// 구체 타입으로 조회 (유연성 감소)
MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class);
Java
복사
3.2. 동일 타입이 여러 개일 경우
// 모든 빈 조회
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
// 특정 빈 이름으로 조회
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
Java
복사
3.3. 상속 관계
부모 타입으로 조회하면 자식 타입도 함께 조회됩니다. 따라서 Object 타입으로 조회하면 모든 스프링 빈이 조회됩니다.
// 부모 타입으로 조회하면 자식 타입도 함께 조회됨
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
Java
복사
4. BeanFactory와 ApplicationContext
4.1. BeanFactory
•
스프링 컨테이너의 최상위 인터페이스
•
스프링 빈 관리와 조회를 담당
•
getBean() 메소드 제공
4.2. ApplicationContext
•
BeanFactory를 상속받은 인터페이스
•
빈 관리 기능 + 다양한 부가 기능 제공
4.3. ApplicationContext가 제공하는 부가 기능
•
메시지소스 활용한 국제화 기능: 다국어 처리
•
환경변수 관리: 로컬, 개발, 운영 환경 구분
•
애플리케이션 이벤트: 이벤트 발행/구독 모델 지원
•
편리한 리소스 조회: 파일, 클래스패스, 외부 등의 리소스 조회
5. 다양한 설정 형식 지원
스프링 컨테이너는 다양한 형식의 설정 정보를 처리할 수 있습니다
5.1. Java 코드 기반 설정
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
Java
복사
5.2. XML 기반 설정
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
Java
복사
// XML 예시
<beans>
<bean id="memberService" class="hello.core.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository" />
</bean>
<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository" />
</beans>
XML
복사
6. 스프링 빈 설정 메타 정보 - BeanDefinition
스프링이 다양한 설정 형식을 지원하는 핵심에는 BeanDefinition이라는 추상화가 있습니다. BeanDefinition은 빈 설정에 대한 메타 정보를 담고 있으며, 스프링 컨테이너는 이 메타 정보를 기반으로 빈을 생성합니다.
6.1. BeanDefinition의 역할
•
스프링 컨테이너가 다양한 설정 형식(Java, XML 등)을 처리할 수 있게 해주는 추상화
•
각 @Bean 또는 <bean> 정의마다 하나의 BeanDefinition 메타 정보 생성
•
설정 형식과 상관없이 일관된 방식으로 빈 관리 가능
6.2. BeanDefinition 주요 정보
•
BeanClassName: 생성할 빈의 클래스명
•
factoryBeanName: 팩토리 빈 사용 시 이름 (예: appConfig)
•
factoryMethodName: 빈 생성 팩토리 메서드 (예: memberService)
•
Scope: 빈의 스코프 (기본값: 싱글톤)
•
lazyInit: 지연 초기화 여부
•
InitMethodName: 초기화 메서드명
•
DestroyMethodName: 소멸 메서드명
•
Constructor arguments, Properties: 의존관계 주입에 사용
graph TD A[스프링 컨테이너] --> B[BeanDefinition] C[XML 설정] --> D[XmlBeanDefinitionReader] --> B E[자바 코드 설정] --> F[AnnotatedBeanDefinitionReader] --> B G[기타 형식 설정] --> H[XXXBeanDefinitionReader] --> B
Mermaid
복사
5.3. BeanDefinition 계층 구조
graph TD A[ApplicationContext] --> B1[AnnotationConfigApplicationContext] A --> B2[GenericXmlApplicationContext] A --> B3[XXXApplicationContext] B1 --> C1[AnnotatedBeanDefinitionReader] B2 --> C2[XmlBeanDefinitionReader] B3 --> C3[XXXBeanDefinitionReader] C1 --> D1(설정 정보 읽기) C2 --> D1 C3 --> D1 D1 --> E[BeanDefinition] E --> F(빈 메타 설정) F --> G[스프링 빈]
Mermaid
복사
7. BeanDefinition의 핵심 이해
스프링은 BeanDefinition이라는 추상화를 통해 다양한 설정 형식을 지원합니다. 설정이 어떤 형식(Java, XML 등)으로 되어 있든, 최종적으로는 BeanDefinition으로 변환되어 스프링 컨테이너에 등록됩니다.
•
Java 코드 기반 설정에서는 AnnotatedBeanDefinitionReader가 AppConfig.class를 읽어 BeanDefinition 생성
•
XML 기반 설정에서는 XmlBeanDefinitionReader가 appConfig.xml을 읽어 BeanDefinition 생성
•
새로운 형식의 설정이 추가되면, 해당 형식에 맞는 XXXBeanDefinitionReader를 구현하여 BeanDefinition 생성
이러한 추상화 계층 덕분에 스프링은 설정 형식에 구애받지 않고 일관된 방식으로 빈을 관리할 수 있습니다.
8. 결론
•
스프링 컨테이너와 빈의 원리를 이해하면 스프링 프레임워크를 더 효과적으로 활용할 수 있습니다.
•
특히 BeanDefinition이라는 추상화 개념은 스프링의 유연성과 확장성의 핵심이며, 다양한 설정 방식을 지원하는 원리가 됩니다.
•
실무에서 BeanDefinition을 직접 다룰 일은 거의 없지만, 스프링의 내부 동작 원리를 이해하는 데 중요한 개념입니다.