Spring Bean의 개념과 생명주기, 그리고 메모리 효율성

2025. 12. 18. 01:02Web/Spring

 

Spring Bean이란 Spring IoC(Inversion of Control) 컨테이너가 관리하는 자바 객체를 의미한다.

일반적인 자바 프로그래밍에서는 개발자가 new 키워드를 사용하여 직접 객체를 생성하고 관리해야 했으나, Spring 프레임워크에서는 이 역할을 프레임워크에게 넘기게 된다. 이렇게 컨테이너에 의해 생성되고 관리되는 객체가 바로 Bean이다.


1. 주요 특징

Spring Bean은 단순한 객체 이상의 의미를 가지며 다음과 같은 핵심적인 특징을 지닌다.

  • IoC (제어의 역전): 객체의 생성, 생명주기 관리, 의존성 설정(DI)을 개발자가 직접 하지 않고 프레임워크가 대신 담당한다.
  • POJO (Plain Old Java Object): 특정 클래스를 상속받거나 복잡한 인터페이스를 구현할 필요 없이, 평범한 자바 객체 형태로 만들 수 있어 유연성이 높다.

등록 방법

주로 @Bean, @Component, @Service, @Repository 등의 어노테이션을 클래스에 붙이거나, XML 설정을 통해 컨테이너에 등록한다.


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

Spring Bean 생명주기

 

Spring Bean은 객체가 생성되고 소멸되기까지 명확한 단계를 거친다. 가장 큰 특징은 객체 생성과 초기화 단계가 분리되어 있다는 점이다.

1. 전체 흐름

  1. 스프링 컨테이너 생성
  2. 스프링 빈 생성 (자바 객체로서 생성자 호출)
  3. 의존관계 주입 (DI)
    • 참고: 생성자 주입(Constructor Injection) 방식을 사용할 경우 빈 생성과 동시에 주입이 일어난다.
  4. 초기화 콜백 (@PostConstruct)
    • 의존성 주입이 완료된 후, 필요한 초기 세팅(데이터 로딩, 검증 등)을 수행한다.
  5. 빈 사용
  6. 소멸 전 콜백 (@PreDestroy)
    • 컨테이너 종료 전 리소스 정리 등을 수행한다.
  7. 스프링 종료

2. 초기화 콜백의 활용 예시 (@PostConstruct)

초기화 단계에서는 단순 객체 생성을 넘어, 실제 애플리케이션 동작에 필요한 디렉터리 생성이나 데이터 검증 로직을 포함할 수 있다.

@Component
public class FileStorageManager {

    @Value("${file.upload.dir}") // yml에서 경로 주입 (/app/uploads)
    private String uploadDir;

    @PostConstruct
    public void validateConfig() {
        File folder = new File(uploadDir);
        
        // 폴더가 없으면 생성 시도
        if (!folder.exists()) {
            boolean created = folder.mkdirs();
            if (!created) {
                // 서버 구동 시 치명적인 오류라면 예외를 던져 앱 구동을 중단
                throw new RuntimeException("업로드 폴더를 생성할 수 없습니다: " + uploadDir);
            }
            System.out.println("업로드 폴더 생성 완료: " + uploadDir);
        }
    }
}

3. Bean 사용과 메모리 성능의 관계

Spring을 사용하는 가장 큰 이유 중 하나는 싱글톤(Singleton) 패턴을 통한 메모리 효율성 극대화다.

1. 싱글톤 (Singleton) 관리

Spring 컨테이너는 기본적으로 Bean을 싱글톤으로 관리한다. 즉, 애플리케이션 구동 시 단 하나의 인스턴스만 생성하여 컨테이너에 등록하고, 이후 들어오는 모든 요청에 대해 이 객체를 공유하여 재사용한다.

 

2. new vs Spring Bean

구분 Spring 없이 (new) Spring Bean 사용 (싱글톤)
동작 방식 클라이언트 요청 100번 → 객체 100번 생성 및 삭제 요청이 100번, 1만 번 와도 객체는 단 1개
메모리 메모리 낭비 심함, 힙(Heap) 사용량 급증 메모리 사용량 일정, 효율 극대화
GC 부하 가비지 컬렉션(GC) 빈도 증가로 인한 오버헤드 객체 생성/삭제가 적어 GC 작업량 감소

 

웹 애플리케이션처럼 동시 요청이 많은 환경에서 매번 객체를 생성하는 것은 치명적이다. Spring의 싱글톤 방식은 힙 메모리에 쌓이는 객체의 수를 줄여 GC(Garbage Collector)의 오버헤드를 감소시키고, 결과적으로 애플리케이션의 응답 속도와 전반적인 성능을 향상시킨다.


4. 주의사항 및 고급 기능

싱글톤 방식은 효율적이지만, 하나의 객체를 여러 사용자가 공유하기 때문에 개발 시 주의가 필요하다.

상태 정보 유지 금지 (Stateless)

싱글톤 객체는 여러 스레드에서 동시에 접근한다. 따라서 Bean 내부 멤버 변수에 사용자별 상태 정보를 저장하면 안 된다.
(ex: 로그인한 유저의 ID, 결제 금액 등)

만약 이를 어길 경우, 다른 사용자의 요청에 의해 데이터가 덮어씌워지는 심각한 동시성 버그가 발생할 수 있다.
Bean은 항상 무상태(Stateless)로 설계하고 로직 처리 위주로 구성해야 한다.


5. 추가 기능: 지연 로딩 (@Lazy)

 

Spring은 기본적으로 구동 시점에 모든 Bean을 생성(Eager Loading)하지만, 메모리가 제한적이거나 사용 빈도가 매우 낮은 Bean이 있다면 @Lazy 어노테이션을 사용하여 실제 호출되는 시점에 객체를 생성하도록 설정할 수 있다. 이를 통해 초기 구동 속도를 높이고 초기 메모리 점유율을 낮출 수 있다.

'Web > Spring' 카테고리의 다른 글

MySQL Master-Slave Replication 설정  (0) 2025.02.20
[Spring] Category 구현하기  (0) 2024.02.21
[Spring] HTTPS 적용하기  (0) 2024.02.17
[Spring] 휴대폰 인증 - 네이버 sens 사용  (0) 2023.08.26
[Spring] 이메일 인증  (0) 2023.08.26