본문 바로가기
language/java

Bean 생성 과정

by 죄니안죄니 2026. 6. 17.
반응형

이 챕터에서는 Reflection → Bean 생성 → DI → Proxy → AOP → Transaction 순서가 가장 자연스럽다.

그래서 이번 글은 단순히

"Bean은 Spring이 관리하는 객체입니다."

수준으로 끝나면 안 된다.

독자가

Spring Boot를 실행하면 내부에서 실제로 무슨 일이 일어나는가?

를 머릿속으로 그릴 수 있어야 한다.


Bean 생성 과정

Spring Boot가 실행되면 내부에서는 무슨 일이 일어날까?

이전 글에서는

Reflection을 이용해서

 
@Service
public class UserService {

}
 

를 발견하고

객체를 생성한 뒤

DI를 수행한다는 것을 배웠다.

하지만 실제 Spring 내부는 훨씬 복잡하다.

Spring은 단순히

 
new UserService();
 

를 실행하는 것이 아니라,

수많은 단계를 거쳐 하나의 Bean을 생성한다.

이번 글에서는

Spring Boot가 시작되는 순간부터 Bean이 완성될 때까지의 전체 흐름을 살펴보자.


먼저 Bean이란?

많은 사람들이

Bean = Spring이 관리하는 객체

라고 외운다.

맞는 말이다.

하지만 조금 더 정확하게 말하면

Spring IoC Container(ApplicationContext)가 생성하고, 관리하고, 생명주기를 제어하는 객체

이다.


예를 들어

 
@Service
public class UserService {

}
 

우리는

 
new UserService();
 

를 작성하지 않는다.


대신

Spring이

ApplicationContext

↓

UserService 생성

↓

관리

↓

필요한 곳에 주입
 

을 수행한다.


Spring Boot 시작

가장 처음 실행되는 코드는

 
@SpringBootApplication
public class Application {

    public static void main(String[] args) {

        SpringApplication.run(
                Application.class,
                args
        );

    }

}
 

이다.


여기서

 
SpringApplication.run(...)
 

한 줄이

수많은 작업을 수행한다.


간단히 표현하면

Application Start

↓

ApplicationContext 생성

↓

Bean 등록

↓

Bean 생성

↓

DI 수행

↓

Application Ready
 

이다.


1단계

Component Scan

먼저

 
@SpringBootApplication
 

을 확인한다.


실제로는

 
@SpringBootApplication

↓

@ComponentScan

↓

@Component

@Service

@Repository

@Controller

탐색
 

이 수행된다.


프로젝트를 스캔하면서

UserService.class

OrderService.class

UserController.class
 

를 찾는다.


2단계

BeanDefinition 생성

여기서 아직 객체를 만들지 않는다.


대신

객체의 설계도만 만든다.


예를 들어

 
@Service
public class UserService {

}
 

Spring 내부

BeanDefinition

------------------------

Class

Scope

Lazy 여부

생성 방식

생성자 정보

------------------------
 

를 생성한다.


즉,

객체

X

----------------

객체를 만들기 위한 정보

O
 

이다.


BeanDefinition이 필요한 이유

Spring은

모든 객체를 한 번에 만들지 않는다.


먼저

UserService

OrderService

ProductService

UserController
 

정보를 모두 수집한다.


그리고

의존 관계를 분석한다.


예를 들어

 
@Service
public class OrderService {

    private final UserService userService;

}
 

Spring은

OrderService

↓

UserService 필요
 

를 먼저 알게 된다.


3단계

Bean 생성

이제 Reflection으로

객체를 생성한다.


 
Constructor<?> constructor =

clazz.getDeclaredConstructor();

constructor.newInstance();
 

즉,

Reflection

↓

Constructor 조회

↓

newInstance()

↓

Bean 생성
 

이다.


4단계

DI(Dependency Injection)

객체를 만들었다고 끝이 아니다.


다음 클래스를 보자.

 
@Service
public class OrderService {

    private final UserService userService;

}
 

Spring은

Bean Container에서

UserService를 찾는다.


BeanContainer

------------------------

UserService

OrderService

------------------------
 

그리고

 
new OrderService(userService);
 

를 Reflection으로 수행한다.


5단계

BeanPostProcessor

많은 사람들이 모르는 단계이다.


Bean 생성

DI 완료

BeanPostProcessor 실행


여기서

Spring은

Bean을 수정하거나

Proxy로 교체할 수 있다.


예를 들어

 
@Transactional
public void save() {

}
 

Spring은

UserService

↓

Transaction Proxy

↓

Bean Container 저장
 

으로 변경한다.


즉,

Container 안에는

실제 객체가 아니라

Proxy가 들어갈 수도 있다.


그림으로 보면

Bean 생성

↓

UserService

↓

BeanPostProcessor

↓

@Transactional 발견

↓

Transaction Proxy 생성

↓

Bean Container 저장
 

6단계

Singleton Cache 저장

기본적으로

Spring Bean은 Singleton이다.


즉,

BeanContainer

------------------------

UserService

OrderService

ProductService

------------------------
 

하나만 생성된다.


Controller

 
@Autowired
UserService userService;
 

Service

 
@Autowired
UserService userService;
 

둘 다

같은 객체를 사용한다.


실제 흐름

Application 시작

Application Start

↓

@ComponentScan

↓

BeanDefinition 생성

↓

Reflection으로 객체 생성

↓

DI 수행

↓

BeanPostProcessor

↓

Proxy 생성(필요 시)

↓

Singleton Cache 저장

↓

Application Ready
 

왜 BeanDefinition이 먼저 필요할까?

예를 들어

 
@Service
class A {

    private B b;

}

@Service
class B {

    private A a;

}
 

Spring이

바로 생성한다면

A 생성

↓

B 필요

↓

B 생성

↓

A 필요

↓

무한 반복
 

이 된다.


BeanDefinition으로

전체 구조를 먼저 분석하기 때문에

순서를 결정할 수 있다.


Bean 생성은 언제 일어날까?

기본적으로

Singleton Bean은

Application Start

↓

즉시 생성(Eager Loading)
 

된다.


하지만

 
@Lazy
@Service
public class UserService {

}
 

라면


Application Start

↓

생성 안 함

↓

처음 사용할 때 생성
 

된다.


실무에서 가장 많이 보는 Bean

Controller

↓

Service

↓

Repository

↓

Configuration

↓

Component
 

모두 Bean이다.


Bean Factory와 ApplicationContext

실제로는

BeanFactory

↓

ApplicationContext
 

구조이다.


BeanFactory

객체 생성
 

기능만 가진다.


ApplicationContext

BeanFactory

+

이벤트

+

국제화

+

AOP

+

환경설정
 

을 포함한다.


그래서

실무에서는 거의 항상

ApplicationContext
 

를 사용한다.


그림으로 전체 정리

Application Start

        │

        ▼

@ComponentScan

        │

        ▼

BeanDefinition 생성

        │

        ▼

Reflection 객체 생성

        │

        ▼

DI 수행

        │

        ▼

BeanPostProcessor

        │

        ▼

@Transactional 발견

        │

        ▼

Proxy 생성

        │

        ▼

Singleton Cache 저장

        │

        ▼

Application Ready
 

Reflection과 연결해서 보면

이전 글에서

Reflection은

Spring이 클래스를 이해하는 눈(Eye)

이라고 했다.

이번 글에서는

Reflection이

Bean 생성

↓

DI 수행

↓

BeanPostProcessor

↓

Proxy 생성
 

까지 이어지는 것을 확인했다.


즉,

Reflection은

Spring Bean 생명주기의 시작점이다.


면접 포인트

Bean이란?

Spring IoC Container(ApplicationContext)가 생성하고 관리하는 객체이다.


Bean 생성 과정

Component Scan

↓

BeanDefinition 생성

↓

Reflection 객체 생성

↓

Dependency Injection

↓

BeanPostProcessor

↓

Proxy 생성

↓

Singleton Cache 저장
 

BeanDefinition이 필요한 이유는?

객체를 생성하기 전에 Bean의 메타데이터와 의존 관계를 먼저 분석하기 위해서이다.


BeanPostProcessor는 무엇인가?

Bean 생성 이후 Bean을 수정하거나 Proxy로 교체할 수 있는 확장 포인트이며, @Transactional, @Async, @Cacheable, AOP 등이 이 과정을 활용한다.


다음 글 추천

다음은 객체 생명주기와 Spring Bean이다.

이 글에서는

new

↓

생성자

↓

DI

↓

@PostConstruct

↓

사용

↓

@PreDestroy

↓

소멸
 

뿐만 아니라,

  • InitializingBean
  • DisposableBean
  • BeanPostProcessor와 실행 순서
  • Singleton / Prototype / Request Scope의 생명주기 차이

까지 연결하면 Spring의 전체 흐름이 완성된다.

반응형

'language > java' 카테고리의 다른 글

Dynamic Proxy와 Spring AOP  (0) 2026.06.17
객체 생명주기와 Spring Bean  (0) 2026.06.17
Reflection과 Spring DI  (0) 2026.06.17
Virtual Thread(Java 21)  (0) 2026.06.17
Stream 개선사항(Java 9~21)  (0) 2026.06.17

댓글