백엔드

[Spring Boot] Spring IoC - 컨테이너, Bean 등록/스코프/생명주기

빡성 2025. 10. 11. 17:29

BeanFactory vs ApplicationContext

둘 다 Spring IoC 컨테이너다. BeanFactory는 가장 기본 스펙, ApplicationContext는 이를 확장해 메시지/이벤트/리소스 로딩 등 부가기능을 제공한다.

Feature BeanFactory ApplicationContext
빈 생성/주입 지원 지원
라이프사이클 통합 관리 제한적 지원
BeanPostProcessor 자동 등록 직접 등록 자동
메시지 소스(국제화) - 지원
이벤트 퍼블리싱 - 지원
리소스 로딩 - 지원

Spring Bean vs JavaBeans

정의
  • Spring Bean: 컨테이너가 생성·주입·생명주기를 관리하는 객체.
  • JavaBeans: 기본 생성자 + getter/setter를 갖춘 POJO 패턴(이름만 비슷하고 다른 개념).

Bean 등록 방법

@Configuration + @Bean (수동 등록)
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
class AppConfig {
  @Bean
  DataSource dataSource() {
    HikariDataSource ds = new HikariDataSource();
    ds.setJdbcUrl("jdbc:h2:mem:testdb");
    ds.setUsername("sa");
    return ds;
  }
}
@Component 계열(자동 등록)
import org.springframework.stereotype.*;

@Service
class UserService { /* ... */ }
ApplicationContext에서 빈 사용
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Component
class AppStartupRunner implements ApplicationRunner {
  private final ApplicationContext ctx;
  @Override public void run(ApplicationArguments args) {
    Greeting g = ctx.getBean(Greeting.class);
    g.sayHello();
  }
}

스테레오타입 애노테이션

  • @Controller: 프레젠테이션 계층(요청 처리, 뷰 반환)
  • @Service: 비즈니스 로직
  • @Repository: 데이터 접근 계층

Bean 스코프

기본은 singleton. 필요 시 prototype, 웹 스코프(request, session, application, websocket) 사용.

예시: singleton/prototype
import org.springframework.context.annotation.*;

@Configuration
class GreetingConfig {
  @Bean @Scope("singleton")
  Greeting englishGreeting() { return new EnglishGreeting(); }

  @Bean @Scope("prototype")
  Greeting koreanGreeting() { return new KoreanGreeting(); }
}

생명주기 훅(초기화/소멸)

@PostConstruct / @PreDestroy
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
class CacheManager {
  @PostConstruct void init(){ System.out.println("warm up cache"); }
  @PreDestroy  void close(){ System.out.println("flush cache"); }
}
InitializingBean / DisposableBean
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.DisposableBean;

class EnglishGreeting implements Greeting, InitializingBean, DisposableBean {
  public EnglishGreeting(){ System.out.println("constructor"); }
  public void sayHello(){ System.out.println("hello world"); }
  @Override public void afterPropertiesSet(){ System.out.println("afterPropertiesSet"); }
  @Override public void destroy(){ System.out.println("destroy"); }
}
@Bean(initMethod/destroyMethod)
import org.springframework.context.annotation.*;

@Configuration
class BeanInitConfig {
  @Bean(initMethod="customInit", destroyMethod="customDestroy")
  Greeting englishGreeting(){ return new EnglishGreeting2(); }
}

class EnglishGreeting2 implements Greeting {
  public void sayHello(){ System.out.println("hello"); }
  public void customInit(){ System.out.println("init"); }
  public void customDestroy(){ System.out.println("destroy"); }
}
세 가지를 함께 쓰면(실행 순서)
@PostConstruct → afterPropertiesSet() → @Bean initMethod → 사용 → @PreDestroy → destroy() → @Bean destroyMethod

BeanPostProcessor

모든 빈의 초기화 전/후를 가로채 커스터마이징할 수 있는 확장 포인트다. 특정 빈에 종속되지 않고 컨테이너 전반에 영향을 줄 수 있다.

예시: 초기화 전/후 로깅
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;

@Configuration
class LoggingPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
    System.out.println("before init: " + name);
    return bean;
  }
  @Override
  public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
    System.out.println("after init: " + name);
    return bean;
  }
}

요약

  • IoC: 흐름/생성/연결의 제어권을 컨테이너로 역전.
  • Spring 컨테이너: ApplicationContext가 Bean을 생성·주입·관리.
  • Bean 등록: @Component(자동) / @Configuration+@Bean(수동).
  • 스코프: singleton 기본, 필요 시 prototype·웹 스코프.
  • 생명주기 훅: @PostConstruct/@PreDestroy, InitializingBean/DisposableBean, @Bean init/destroy.
  • 확장: BeanPostProcessor로 초기화 전후 훅 가로채기.

'백엔드' 카테고리의 다른 글

[Spring Security] Basic Authentication  (0) 2025.10.23
[Spring Boot] DI(Dependency Injection)  (2) 2025.10.13
[Spring Boot] Spring IoC - 개념  (0) 2025.10.11
[SpringBoot] Bean이란?  (0) 2025.10.11
[Spring Boot] Framework  (0) 2025.10.11