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가 관리하는 객체 인스턴스
  • 동작 원리:
    1. 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. ‌