Spring 교과서: Chapter2
Spring 교과서 정리
· 3 min read
학습 날짜: 2025.12.17
핵심 키워드: Bean, Context, @Bean, Stereotype, IoC
1. Chapter2 목표 #
- Bean과 Context에 대한 이해
- Context가 관리할 수 있는 Bean을 생성하는 3가지 방법 학습
2. Context와 Bean 핵심 개념 #
Bean #
- 정의: Spring Context가 관리하는 객체 인스턴스
- 동작 원리:
- Bean이 AnnotationConfigApplicationContext가 인식될 수 있도록 설정
Context #
- 정의: 애플리케이션 메모리 공간 안에 있는 프레임워크가 관리할 객체 인스턴스들을 모아 두는 곳
- IoC 컨테이너: Spring은 애플리케이션에 있는 객체들을 전혀 모르며, 오직 이 컨텍스트 안에 들어온 객체만 인식하고 관리할 수 있다.
3. Bean 추가 코드 구현 #
3.1 [구현 방식 1: @Bean 사용 ] #
가장 기본적인 수동 등록 방식
@Configuration
public class ProjectConfig {
@Bean
@Primary
Penguin penguin() {
return new Penguin("Pingu");
}
}
// 사용
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
var bean = context.getBean(Penguin.class);
graph LR
subgraph "설정 <br>(Configuration)"
A[ProjectConfig 클래스]
A --> B{"@Bean 메서드 작성"};
end
C["스프링 컨테이너<br>(ApplicationConte)"] -->|1. 시작 시 설정 로드| A;
C -->|2. 메서드 호출| B;
B -->|3. 인스턴스 반환| D(객체);
D -->|4. 빈으로 등록 및 관리| C;
style A font-size:25px
style B fill:#f9f,stroke:#333,stroke-width:2px,color:#000,font-size:25px
style C font-size:25px
style D fill:#fff,stroke:#333,stroke-width:2px,color:#000,font-size:25px
3.2 [구현 방식 2: 스테레오 타입 @Component 사용] #
자동 감지 및 등록 방식
@Configuration
@ComponentScan(basePackageClasses = Main.class)
public class ProjectConfig {
}
@Component
public class Tiger {
@PostConstruct
public void init() {
this.name = "Tigger";
}
}
// 사용
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
var bean = context.getBean(Tiger.class);
graph TD
subgraph "설정 및 클래스"
A["@ComponentScan 설정<br>(스캔 대상 패키지 지정)"]
B["Tiger 클래스<br>(@Component 붙임)"]
end
C["스프링 컨테이너<br>(ApplicationContext)"] -->|1. 스캔 시작| A;
C -.->|2. 패키지 뒤적뒤적...| B;
B -->|"3. 발견! (자동 감지)"| C;
C -->|4. 알아서 인스턴스 생성| D(Tiger 객체);
D -->|5. 빈으로 등록 및 관리| C;
style A font-size:16px
style B fill:#ccf,stroke:#333,stroke-width:2px,color:#000,font-size:16px
style C font-size:16px
style D fill:#fff,stroke:#333,stroke-width:2px,color:#000,font-size:16px
3.3 [구현 방식 3: 프로그래밍 방식 빈 추가] #
조건부 로직에 따른 동적 등록 방식
@Configuration
public class ProjectConfig {
}
// 런타임에 동적으로 빈 등록
var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
Elephant elephant = new Elephant("Dumbo");
Supplier<Elephant> supplier = () -> elephant;
context.registerBean("elephant1", Elephant.class, supplier);
var bean = context.getBean(Elephant.class);
graph TD
A[애플리케이션 실행 중...];
A --> B{"런타임 조건 확인<br>(예: 특정 환경변수 존재?)"};
B -- YES --> C["context.registerBean(Elephant.class)<br>코드 실행"];
C -->|1. 등록 명령| D["스프링 컨테이너<br>(ApplicationContext)"];
D -->|2. 즉시 인스턴스 생성| E(Elephant 객체);
E -->|3. 빈으로 등록 및 관리| D;
B -- NO --> F[빈 등록 안 함];
style C fill:#ff9,stroke:#333,stroke-width:2px,color:#000
style E fill:#fff,stroke:#333,stroke-width:2px,color:#000
4. Bean 추가 방식 비교 및 정리 #
| 구분 | @Bean (Penguin) | 스테레오타입 (Tiger) | 프로그래밍 방식 (Elephant) |
|---|---|---|---|
| 특징 | @Bean을 이용하여 메서드로 생성 | @ComponentScan과 @Component 이용 | context.registerBean() 사용 |
| 장점 | ProjectConfig에서 직관적인 빈 생성 가능 라이브러리 클래스 등록 용이 | 하나씩 생성할 필요 없이 자동으로 클래스들이 빈으로 등록됨 | 런타임 조건(if문 등)을 바탕으로 원하는 빈들만 동적으로 생성 가능 |
| 단점 | 하나씩 모두 설정 파일에서 생성 메서드를 작성해야 함 | 생성 시 원하는 값을 주입하기 어려워 @PostConstruct 등으로 추가 설정 필요 | registerBean 코드를 작성하는 과정이 추가적으로 필요하고 복잡함 |
| 언제 쓰는가? | 외부 라이브러리 객체이거나, 수동으로 생성할 때 | 보통의 경우 (Most Common) | 특정 조건에 따라 빈을 등록/미등록 해야 할 때 |
5. 정리 #
- 실무에서는 스테레오타입(@Component) 어노테이션을 가장 많이 사용한다.
- 복잡한 조건 기반의 빈 생성 시 프로그래밍 방식을 이용하여 register 한다.
- 외부 라이브러리 설정 등 특수한 경우 @Bean을 이용하여 수동 생성한다.
Reference #
[1]스프링 교과서. 2024.