티스토리 뷰

IT/Spring

Spring Bean과 생명주기 - Bean의 생성부터 소멸까지, 내부에서는 어떤 일이 벌어질까?

Stv 2025. 5. 12. 21:37

목차


    Spring의 핵심은 결국 "Bean 관리"이다.
    이번 포스팅에서는 단순한 순서를 넘어서, Bean의 생성 -> 초기화 -> 사용 -> 소멸에 이르는 전 과정을 메서드, 인터페이스, 어노테이션, 내부 메커니즘까지 완전히 정복할 수 있도록 정리하겠다.

     

    1. Spring Bean 이란?

    Spring Bean은 Spring IoC 컨테이너가 관리하는 객체이다.
    즉, 개발자가 new로 만들지 않고, Spring이 대신 생성하고 관리하는 객체가 Bean이다.

     

    @Component
    public class UserService { ... }
    • 위 클래스는 컴포넌트 스캔 대상이 되어 Bean으로 등록된다.
    • 다른 객체에서 @Autowired, @Inject, @Bean 등을 통해 주입(Injection) 받을 수 있다.

    🌀 2. Spring Bean 생명주기 전체 흐름 요약

    애플리케이션 시작 →
    Bean 정의 읽기 →
    Bean 인스턴스 생성 →
    의존성 주입 →
    초기화 →
    사용 →
    소멸

     

    • Spring의 핵심인 ApplicationContext가 이 전 과정을 주도한다.
    • 구체적으로는 아래 단계를 참고하기 바란다.

    3. Bean 생명주기 단계별 상세 설명

    1. BeanDefinition 등록
      • Spring이 클래스 정보를 메타데이터로 추출하여 BeanDefinition 객체로 저장
    2. Bean 생성
      • 객체 인스턴스를 생성 : new 또는 ObjectFactory
    3. 의존성 주입 (Dependency Injection)
      • 생성자, Setter, Field 등을 통해 필요한 Bean 주입
    4. Aware 인터페이스 호출 (선택적) : Bean이 자신을 둘러싼 Spring 컨텍스트 정보에 접근해야 할 때 사용
      • BeanNameAware : 자신의 Bean 이름을 알 수 있음
      • BeanClassLoaderAware, ApplicationContextAware 등
    5. 초기화 콜백
      • @PostConstruct
      • InitializingBean.afterPropertiesSet()
      • @Bean(initMethod = "...")
    6. 사용 (Use Phase)
      • 빈이 실제 애플리케이션에서 사용되는 시점
    7. 소멸 콜백 (컨테이너 종료 시)
      • @PreDestroy
      • DisposableBean.destroy()
      • @Bean(destroyMethod = "...")

    4. 초기화 / 소멸 관련 주요 인터페이스 & 어노테이션

    단계 방식 설명
    초기화 @PostConstruct 빈 생성 후 한 번 호출, 가장 많이 사용
    초기화 InitializingBean afterPropoertiesSet() 메서드 구현
    초기화 @Bean(initMethod = "...") XML/Java Config에서 지정 가능
    소멸 @PreDestroy 컨테이너 종료 직전 호출
    소멸 DisposableBean destroy() 메서드 구현
    소멸 @Bean(destroyMethod = "...") 명시적 소멸 메서드 지정

     

    5. Bean 생명주기 전체 흐름 (시퀀스 다이어그램)

    [ApplicationContext]
         |
         v
    1. BeanDefinition 등록
         |
    2. 인스턴스 생성 (Constructor or Factory)
         |
    3. 의존성 주입 (DI)
         |
    4. Aware 인터페이스 호출 (선택)
         |
    5. 초기화 콜백 (@PostConstruct 등)
         |
    6. 빈 사용
         |
    7. 소멸 콜백 (@PreDestroy 등)

     


    💎6. 실무에서 많이 쓰는 패턴 예시

    예 : 커넥션 풀, 리소스 연결  Bean

    @Component
    public class RedisClient {
    
        private RedisConnection connection;
    
        @PostConstruct
        public void init() {
            connection = new RedisConnection();
            connection.connect();
        }
    
        @PreDestroy
        public void shutdown() {
            connection.disconnect();
        }
    }
    • Bean 생성 시 연결 -> 종료 시 정리
    • @PostConstruct와 @PreDestroy는 실무에서 가장 안정적인 방식

    🧠 7.Spring과 SOLID, Bean 생명주기 관계

    원칙 적용 포인트
    SRP 초기화/소멸 책임을 별도로 분리 가능
    OCP init/destroy 메서드 교체 가능
    DIP 초기화 시 의존성 주입을 통해 구현체 교체
    LSP Bean이 상위 인터페이스로도 문제 없이 동작
    ISP Aware 인터페이스로 관심사 분리 가능 (단일 목적)

     

    8. 프로토타입(Prototype) Bean 생명주기 주의사항

    • singleton : ApplicationContext가 Bean을 생성하고 소멸까지 관리
    • prototype : Bean만 생성 -> 소멸은 개발자가 책임
    @Bean
    @Scope("prototype")
    public SomeBean prototypeBean() {
        return new SomeBean();
    }
    • @PreDestroy, destroy()가 호출되지 않음
    • ex) 상태를 가지는 임시 객체(파서)를 필요할 때마다 생성하고 필요 시 명시적으로 close() 등을 호출해 자원을 정리하는데 사용

    ✅마무리 요약

    • Spring Bean은 컨테이너가 생성/주입/초기화/소멸까지 완전 관리
    • 생명주기 후킹을 위해 다양한 방법 존재 (@PostConstruct, @PreDestroy 등)
    • Bean 생명주기를 정확히 이해하면, 리소스 관리, 테스트, 동시성 문제 방지에 큰 도움이 된다.
    • Spring을 "사용"만 하는 단계에서 "이해"하는 개발자로 넘어가려면 생명주기 이해는 필수

    🔜 다음 포스팅에서는 Spring의 DI 방식 완정 정복 - 생성자/필드/세터 주입, 그리고 언제 어떻게 써야 하는가? 라는 주제로 내용을 다뤄보려고 한다:)