Spring IoC & DI 완전 정복: Chapter 5. BeanDefinition과 Bean 생성 과정

2026. 7. 22. 14:49·🍃SpringBoot

Chapter 5. BeanDefinition과 Bean 생성 과정

"Spring은 왜 객체를 관리하기 전에, 먼저 객체의 설계도를 관리할까?"

 

앞 장에서는 Spring Container가 Bean을 생성하고 관리하는 실행 환경이라는 점을 살펴보았다. 또한 Bean은 특별한 객체가 아니라 Spring Container가 관리하는 객체라는 사실도 확인했다. 그렇다면 이제 자연스럽게 새로운 질문이 생긴다.

"Spring은 어떤 Bean을 생성해야 하는지 어떻게 알고 있을까?"

애플리케이션에는 수십 개, 많게는 수천 개의 Bean이 존재한다. Spring은 이 모든 객체를 무작정 생성하지 않는다. 먼저 어떤 객체를 생성해야 하는지, 어떻게 생성해야 하는지, 어떤 의존성을 가져야 하는지에 대한 정보를 수집한다. 그리고 그 정보를 바탕으로 실제 Bean을 생성한다. Spring에서 이러한 객체의 설계도 역할을 하는 것이 바로 BeanDefinition이다. 이번 장에서는 BeanDefinition이 무엇인지, 왜 Spring이 Bean보다 BeanDefinition을 먼저 관리하는지, 그리고 Bean이 생성되기까지 어떤 과정을 거치는지를 다룬다.

5.1 Spring은 왜 Bean을 바로 생성하지 않을까?

처음 Spring을 접하는 개발자는 흔히 다음과 같은 단순한 흐름을 떠올리기 쉽다.

  • [ @Component 발견 ] ──> [ Bean 생성 ]

하지만 실제 Spring의 내부 동작은 훨씬 치밀하다. Spring은 `@Component`를 발견했다고 해서 곧바로 메모리에 객체를 할당하지 않는다. 대신 먼저 BeanDefinition이라는 메타데이터를 수집하고 생성한다.

여기서 가장 중요한 핵심은 Bean보다 BeanDefinition이 먼저 존재한다는 점이다.
Spring은 실체(객체)를 만들기 전에, 객체를 만드는 '방법과 규칙'을 정의한 정보부터 체계적으로 관리한다.

5.2 BeanDefinition이란?

BeanDefinition을 한 문장으로 정의하면 다음과 같다.

  • BeanDefinition: Bean을 생성하기 위한 메타데이터(Metadata)

메타데이터란 데이터를 설명하는 데이터다. 즉, BeanDefinition은 인스턴스화된 Bean 자체가 아니라 Bean의 속성과 생성 방식을 설명하는 명세서다. 예를 들어 MemberService라는 Bean이 있다고 가정하자. Spring은 이 객체를 바로 저장하지 않고, 먼저 다음과 같은 메타데이터 구조체로 정리한다.

메타데이터 항목 예시 내용 설명
Bean Class Name MemberService.class 생성할 실제 클래스 타입
Bean Name memberService Container 내에서 구분할 식별자
Scope singleton 객체의 생존 범위 및 관리 방식
Lazy Init false 지연 로딩 여부
Init / Destroy Method @PostConstruct, @PreDestroy 초기화 및 소멸 콜백 메서드
Dependencies MemberRepository 주입받아야 할 의존성 정보

이처럼 Bean 하나를 안전하고 정확하게 생성하는 데 필요한 모든 레시피가 BeanDefinition에 담긴다.

5.3 BeanDefinition은 왜 필요한가?

여기서 결정적인 질문이 던져진다.

"왜 이렇게 번거롭게 중간에 설계도를 다리를 놓아 만드는가?"

 

그 이유는 Spring이 다양한 Bean 등록 방식을 단 하나의 통일된 메커니즘으로 처리하기 위함이다.
Bean을 등록하는 방법은 시대와 상황에 따라 다양하게 발전했다.

1. 컴포넌트 스캔 (어노테이션 기반)

@Component
public class MemberService {}

2. 자바 설정 파일 (Java Config)

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {
        return new MemberService();
    }
}

3. XML 설정 (레거시)

<bean id="memberService" class="com.example.MemberService"/>

등록 방식과 구문은 제각각 다르지만, Spring은 이를 읽어들여 내부적으로 BeanDefinition이라는 단일 규격으로 변환한다.

BeanDefinition 덕분에 Spring Container는 '설정 정보를 읽는 역할'과 '실제 객체를 생성하는 역할'을 완전히 분리할 수 있다. 이것이 바로 Spring이 객체지향의 단일 책임 원칙(SRP)과 역할과 구현의 분리를 극대화하여 20년 넘게 다양한 설정 형식을 유연하게 품어온 비결이다.

5.4 BeanDefinition은 어디에 저장될까?

생성된 BeanDefinition은 어디에 보관될까? 이 역할을 담당하는 것이 앞서 다룬 BeanFactory, 그리고 실무에서 가장 대표적으로 쓰이는 구현체인 DefaultListableBeanFactory다. Spring은 수집된 BeanDefinition을 내부적으로 ConcurrentHashMap 구조에 보관한다.

// DefaultListableBeanFactory 내부 구조 (개념도)
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

이 맵은 "이미 생성되어 메모리에 떠 있는 객체 목록"이 아니다. "향후 언제든 찍어낼 수 있는 객체들의 설계도 보관함"이다. 필요한 시점이 오면 Spring은 이 맵에서 설계도를 꺼내 실제 Bean을 인스턴스화한다.

5.5 Bean 생성은 언제 시작될까?

설계도만 모아둔 상태에서, 실제 Bean 생성을 드라이브하는 스위치는 언제 켜질까? Spring Boot 애플리케이션이 구동되면 ApplicationContext가 초기화되면서 내부적으로 핵심 메서드인 refresh()를 호출한다.

 

refresh() 메서드란?

Spring Container의 모든 설정과 환경을 준비하고, Bean 생성을 진입시키는 Spring 초기화 과정의 총괄 컨트롤러다.

refresh() 내부에서는 Container에 필요한 기본 인프라를 구축한 뒤, beanDefinitionMap에 등록된 설계도들을 바탕으로 본격적인 객체 생성 작업에 돌입한다.

5.6 Bean 생성 과정 (5단계)

드디어 설계도가 메모리 상의 실제 객체로 구현되는 순간이다.
Spring은 BeanDefinition을 바탕으로 다음 5단계를 철저하게 준수하며 Bean을 완성한다.

  1. Instantiate (인스턴스화)
    설계도에 지정된 클래스의 생성자를 호출하여 객체를 메모리에 올린다.
    이 시점의 객체는 아직 의존성이 연결되지 않은 순수한 '빈 껍데기' 상태다.
  2. Populate (의존성 주입)
    생성된 객체에 필요한 의존성을 찾아 주입한다. `@Autowired`나 필드/수정자 주입이 이 단계에서 일어난다.

    바로 다음 장에서 깊이 다룰 Dependency Injection(DI)의 핵심 수행 지점이다.
  3. Initialize (초기화)
    객체 생성이 완료되고 의존성까지 주입된 후, `@PostConstruct`나 `InitializingBean()` 등의 초기화 메서드를 호출한다.
    외부 리소스 연결 등 객체가 정상 동작하기 위한 준비 작업을 마친다.
  4. BeanPostProcessor (Bean 후처리기)
    생성된 Bean을 최종 전달하기 직전에 가공한다.
    필요하다면 AOP 구현을 위해 원본 객체를 감싸는 프록시(Proxy) 객체로 교체하거나 추가 기능을 입히는 곳이 바로 이 단계다.
  5. Singleton Cache 등록
    모든 검증과 가공이 끝난 완제품 Bean은 Container의 Singleton Registry(Singleton Cache)에 저장된다. 이후 애플리케이션에서 동일한 Bean을 요청(`getBean()`)하면, 새로 생성하지 않고 이 캐시에서 이미 만들어진 객체를 즉시 반환한다.

5.7 전체 생성 흐름 한눈에 보기

지금까지 다룬 모든 과정을 하나의 거대한 파이프라인으로 연결하면 다음과 같다.

이 흐름을 이해하고 나면, 향후 배우게 될 DI, BeanPostProcessor, AOP, Scope, Lifecycle 등의 고급 개념들이 모두 이 파이프라인의 특정 위치에 조립되는 부품임을 깨닫게 된다.

Chapter 5 핵심 정리

  1. 설계도 우선주의 (BeanDefinition)
    Spring은 Bean을 무작정 만들지 않고, 메타데이터인 BeanDefinition을 먼저 수집하고 관리한다.
  2. 역할과 구현의 분리
    @Component, @Bean, XML 등 다양한 등록 방식은 모두 BeanDefinition이라는 단일 규격으로 추상화된다.
  3. BeanFactory의 진짜 역할
    BeanFactory는 완성된 객체 목록뿐만 아니라, 객체를 찍어낼 수 있는 BeanDefinitionMap을 보관하고 관리하는 주체다.
  4. refresh() 스위치
    ApplicationContext가 초기화될 때 호출되는 refresh() 메서드가 BeanDefinition을 기반으로 실제 Bean 생성을 구동한다.
  5. Bean 생명의 5단계 파이프라인

'🍃SpringBoot' 카테고리의 다른 글

Spring IoC & DI 완전 정복: Chapter 7. BeanPostProcessor와 Spring의 확장 포인트  (0) 2026.07.22
Spring IoC & DI 완전 정복: Chapter 6. Spring은 의존성을 어떻게 해결할까?  (0) 2026.07.22
Spring IoC & DI 완전 정복: Chapter 4. Spring Container는 무엇인가?  (0) 2026.07.22
Spring IoC & DI 완전 정복: Chapter 3: "제어를 프레임워크에게 넘긴다는 것은 무슨 의미일까?"  (0) 2026.07.22
Spring IoC & DI 완전 정복: Chapter 2: "객체는 왜 스스로 필요한 객체를 만들면 안 될까?"  (1) 2026.07.22
'🍃SpringBoot' 카테고리의 다른 글
  • Spring IoC & DI 완전 정복: Chapter 7. BeanPostProcessor와 Spring의 확장 포인트
  • Spring IoC & DI 완전 정복: Chapter 6. Spring은 의존성을 어떻게 해결할까?
  • Spring IoC & DI 완전 정복: Chapter 4. Spring Container는 무엇인가?
  • Spring IoC & DI 완전 정복: Chapter 3: "제어를 프레임워크에게 넘긴다는 것은 무슨 의미일까?"
limdaeil
limdaeil
limdaeil 님의 블로그 입니다.
  • limdaeil
    limdaeil
    limdaeil
  • 전체
    오늘
    어제
    • 분류 전체보기 (82) N
      • 💭Retrospective (21)
      • 🥕FrontEnd (0)
      • 🐬MySQL (1)
      • 🐍Python (5)
      • 🍃SpringBoot (33) N
      • ☕Java (1)
      • ♾️Devops (1)
      • 🌎Network (2)
      • 📚Read & 👨‍🏫Course (10)
      • Programmers (1)
      • 🧪Test (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    한빛아카데미
    junit
    나는리뷰어다
    Python
    Spring
    DI
    IoC
    책
    회고
    distributed lock
    jwt
    Mockito
    서평단
    optimistic rock
    redis
    한빛미디어
    spring boot
    MySQL
    Concurrency
    gradle
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
limdaeil
Spring IoC & DI 완전 정복: Chapter 5. BeanDefinition과 Bean 생성 과정
상단으로

티스토리툴바