본문 바로가기
Backend

[Spring] 빈 라이프 사이클과 범위

by persi0815 2024. 12. 10.
'초보 웹 개발자를 위한 스프링 5 프로그래밍 입문' 챕터 5를 읽고 정리한 내용입니다. 

 

Spring에서는 스프링 컨테이너가 빈(Bean)의 생성부터 소멸까지의 전 과정을 관리한다. 빈(Bean)은 스프링 컨테이너의 라이프사이클을 따르며, 객체가 생성된 후 초기화되고, 컨테이너가 종료되면 소멸된다. 또한, 스프링 빈의 범위(Scope) 에 따라 동일한 객체를 공유할 수도 있고, 새로운 객체를 매번 생성할 수도 있다.

 

이 글에서는 스프링 빈의 라이프사이클과 범위에 대해 자세히 알아본다.

 

1. 스프링 컨테이너와 빈의 라이프사이클

스프링 컨테이너의 역할

스프링 컨테이너는 설정 클래스를 읽어 빈 객체를 생성하고, 각 빈을 연결(의존 주입)하며, 전체 라이프사이클을 관리한다.
즉, 스프링 컨테이너의 라이프사이클에 따라 빈 객체도 생성과 소멸이라는 라이프사이클을 갖는다.

 

빈의 라이프사이클 단계

  1. 빈 객체 생성 → 컨테이너가 설정 정보를 읽고, 빈 객체를 생성
  2. 의존성 주입(DI, Dependency Injection) → 생성된 빈에 필요한 의존 객체를 주입
  3. 초기화(Initialization) → 빈이 사용 준비 완료 (ex. DB 연결, 설정값 로드)
  4. 사용(Usage) → 빈 객체가 컨테이너 내부에서 사용됨
  5. 소멸(Destruction) → 컨테이너 종료 시 빈이 소멸됨 (ex. DB 연결 해제, 리소스 정리)

예시) 데이터베이스 연결 관리

@Component
public class DatabaseConnection {
    public void connect() {
        System.out.println("데이터베이스 연결 완료");
    }

    public void close() {
        System.out.println("데이터베이스 연결 해제");
    }
}

 

 

초기화 단계에서 데이터베이스 연결이 생성되고, 사용 단계에서 연결 유지, 소멸 단계에서 연결 해제된다. 

 

2. 빈 라이프사이클 인터페이스 (InitializingBean, DisposableBean)

스프링 컨테이너는 빈 객체의 초기화 및 소멸 시, 특정 메서드를 호출하여 라이프사이클을 관리한다. 이를 위해 Spring에서는 InitializingBean, DisposableBean 인터페이스를 제공한다.

 

빈 객체의 초기화 (InitializingBean 인터페이스)

InitializingBean 인터페이스를 구현하면 빈이 초기화될 때 afterPropertiesSet() 메서드가 자동으로 호출된다.

@Component
public class ExampleBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("빈 초기화 완료!");
    }
}

 

컨테이너가 빈을 생성한 후 afterPropertiesSet() 메서드를 실행하여 초기화 작업 수행한다. 

 

빈 객체의 소멸 (DisposableBean 인터페이스)

DisposableBean 인터페이스를 구현하면 빈이 소멸될 때 destroy() 메서드가 자동으로 호출된다.

 

@Component
public class ExampleBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("빈 소멸!");
    }
}

 

컨테이너가 종료되면 destroy() 메서드가 실행되어 리소스를 정리한다. 

 

3. @Bean을 사용한 커스텀 초기화 및 소멸 메서드 지정

위 인터페이스를 구현하지 않더라도, 설정 클래스에서 @Bean을 사용하여 직접 초기화 및 소멸 메서드를 지정할 수 있다.

 

@Bean(initMethod, destroyMethod) 사용

@Configuration
public class AppConfig {
    @Bean(initMethod = "connect", destroyMethod = "close")
    public DatabaseConnection databaseConnection() {
        return new DatabaseConnection();
    }
}
  • initMethod = "connect" → 빈이 생성될 때 connect() 메서드를 실행
  • destroyMethod = "close" → 빈이 소멸될 때 close() 메서드를 실행

 

@PostConstruct, @PreDestroy 애노테이션 활용

Spring에서는 @PostConstruct와 @PreDestroy 애노테이션을 활용해 초기화와 소멸 메서드를 지정할 수도 있다.

@Component
public class ExampleBean {
    
    @PostConstruct
    public void init() {
        System.out.println("빈 초기화 완료!");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("빈 소멸!");
    }
}
  • @PostConstruct → 빈이 생성될 때 실행
  • @PreDestroy → 빈이 소멸될 때 실행

 

4. 스프링 빈의 범위(Scope)

스프링 컨테이너는 기본적으로 모든 빈을 하나만 생성(싱글톤) 한다. 하지만, 특정 상황에서는 매번 새로운 인스턴스를 생성해야 하는 경우도 있다. 이때, 빈의 범위(Scope) 를 지정하면 생성 방식이 달라진다.

 

빈의 범위 (Scope) 종류

singleton (기본값) 컨테이너에서 한 번만 생성 (전역적으로 공유)
prototype 빈을 요청할 때마다 새로 생성
request HTTP 요청별로 새로운 빈 생성 (웹 애플리케이션)
session HTTP 세션별로 새로운 빈 생성 (웹 애플리케이션)

 

singleton (기본값)

singleton 스코프는 컨테이너 내에서 단 하나의 인스턴스만 유지한다.

@Bean
@Scope("singleton")
public DatabaseConnection databaseConnection() {
    return new DatabaseConnection();
}

 

컨테이너가 시작될 때 단 한 개의 빈을 생성하여, 모든 요청에서 동일한 객체를 참조한다. 

 

prototype (매번 새로운 객체 생성)

prototype 스코프를 지정하면 매번 빈을 요청할 때마다 새로운 인스턴스가 생성된다.

@Bean
@Scope("prototype")
public DatabaseConnection databaseConnection() {
    return new DatabaseConnection();
}

 

새로운 요청이 발생할 때마다 새로운 객체가 생성되어 각 요청에서 독립적인 상태를 유지 할 수 있다. 
다만, 스프링 컨테이너가 소멸 메서드를 관리하지 않아, 개발자가 직접 리소스 정리해야 한다.