어제 오늘 내일

[Spring Boot] 빈(Bean)의 탄생과 죽음: 생명주기(Lifecycle)와 스코프(Scope) 완벽 정리 본문

IT/SpringBoot

[Spring Boot] 빈(Bean)의 탄생과 죽음: 생명주기(Lifecycle)와 스코프(Scope) 완벽 정리

hi.anna 2026. 3. 9. 00:36

 

지난 시간, 우리는 new 키워드 없이 스프링 컨테이너가 객체(Bean)를 대신 관리해 주는 의존성 주입(DI)에 대해 알아봤습니다. 그렇다면 스프링은 이 빈들을 언제 만들고, 언제 없앨까요?

오늘은 애플리케이션의 성능과 안정성에 직결되는 빈의 생명주기(Lifecycle)스코프(Scope)에 대해 명쾌하게 정리해 드립니다.

 


 

1. 스프링 빈의 생명주기 (Lifecycle)

일반적인 자바 객체는 new로 생성하고 더 이상 쓰지 않으면 가비지 컬렉터(GC)가 알아서 수거해 갑니다. 하지만 스프링 빈은 조금 더 복잡하고 정교한 과정을 거칩니다.

빈이 생성되고 소멸되는 순서

스프링 컨테이너가 구동될 때 다음과 같은 흐름으로 빈이 관리됩니다.

  1. 스프링 컨테이너 생성
  2. 스프링 빈 생성 (객체화)
  3. 의존관계 주입 (DI - Setter나 Field 주입 시점)
  4. 초기화 콜백 (빈이 완전히 생성된 후 할 일)
  5. 사용 (애플리케이션 로직 수행)
  6. 소멸 전 콜백 (죽기 전에 할 일)
  7. 스프링 종료

핵심 포인트: "객체 생성"과 "초기화"는 분리되어야 합니다.
생성자는 파라미터를 받고 메모리를 할당하는 역할에만 집중하고, 무거운 초기화 작업(DB 연결, 외부 API 호출 등)은 의존성 주입이 다 끝난 뒤인 초기화 단계에서 하는 것이 유지보수에 좋습니다.



 

2. 개발자가 개입할 수 있는 시점: 콜백(Callback)

"빈이 다 만들어지면 DB 연결을 미리 해두고 싶어!" 혹은 "서버가 꺼질 때 안전하게 연결을 끊고 싶어!"
이럴 때 사용하는 것이 바로 콜백 메서드입니다.

과거에는 복잡한 인터페이스를 썼지만, 지금은 어노테이션 딱 두 개만 기억하면 됩니다. (자바 표준인 JSR-250이라 스프링 외에서도 쓰입니다!)

① 초기화: @PostConstruct

의존성 주입이 끝난 직후 실행됩니다.

@Component
public class DatabaseConnector {

    @PostConstruct
    public void init() {
        System.out.println("초기화: 빈 생성 & DI 완료 후 딱 한 번 실행됨!");
        // 여기서 DB 연결이나 데이터 로딩을 합니다.
    }
}

② 소멸: @PreDestroy

컨테이너가 종료되기 직전에 실행됩니다.

    @PreDestroy
    public void close() {
        System.out.println("종료: 빈 소멸 직전 실행됨!");
        // 리소스 반환, 연결 종료 등을 합니다.
    }
}

 

 


 

3. 빈 스코프 (Bean Scope)

"이 빈은 언제까지 살아있나요?"라는 질문에 대한 대답입니다. 스프링은 기본적으로 싱글톤(Singleton)을 사용하지만, 상황에 따라 다르게 설정할 수 있습니다.

스코프 종류 설명 특징
싱글톤 (Default) 컨테이너 시작부터 종료까지 단 하나만 존재 가장 기본! 성능 좋음. 상태를 공유하므로 주의 필요.
프로토타입 (Prototype) 요청할 때마다 새로운 객체를 생성해서 반환 스프링은 생성까지만 관리하고 버림. (소멸 메서드 호출 안 됨)
웹 스코프 (Request) HTTP 요청 하나당 하나씩 생성되고 소멸 사용자 A의 요청과 B의 요청이 서로 섞이지 않음.

 

싱글톤(Singleton) 사용 시 주의할 점 ★

스프링 빈은 기본적으로 하나만 만들어져서 여러 쓰레드가 공유합니다. 따라서 무상태(Stateless)로 설계해야 합니다.

  • 나쁜 예: 특정 클라이언트의 돈, 정보 등을 필드 변수에 저장하면 큰일 납니다! (다른 사람이 그 값을 볼 수 있음)
  • 좋은 예: 읽기 전용 상수나, 값을 공유하지 않는 지역 변수, 파라미터 등을 사용하세요.

 

프로토타입(Prototype)은 언제 쓰나요?

@Scope("prototype")
@Component
public class MyPrototypeBean { ... }

자주 쓰이지는 않지만, 사용할 때마다 독립적인 상태를 가져야 하는 빈이 필요할 때 사용합니다. 단, 종료 메서드(@PreDestroy)가 호출되지 않으므로 사용자가 직접 리소스를 정리해야 한다는 점을 잊지 마세요.

 


 

마치며

오늘 내용을 세 줄로 요약해 볼까요?

  1. 스프링 빈은 생성 -> 의존성 주입 -> 초기화(@PostConstruct) -> 사용 -> 소멸(@PreDestroy)의 과정을 거친다.
  2. 기본적으로 빈은 싱글톤(Singleton)이며, 애플리케이션 전체에서 딱 하나만 존재한다.
  3. 싱글톤 빈은 여러 곳에서 공유되므로 상태 정보(멤버 변수)를 저장하지 않도록 주의해야 한다.

이 개념을 확실히 잡고 가야 나중에 "왜 내 데이터가 덮어씌워졌지?" 같은 끔찍한 동시성 이슈를 피할 수 있습니다.

 

 

반응형
Comments