[Basic-5] 싱글톤 컨테이너와 CGLIB의 동작 원리

2025. 12. 30. 13:04·Spring/Core

 대부분의 스프링 애플리케이션은 웹 애플리케이션이다. 웹 환경은 수많은 고객이 동시에 요청을 보내는 특성을 가진다. 이러한 환경에서 스프링이 어떻게 수만 개의 객체 요청을 효율적으로 처리하는지 그 핵심 원리인 싱글톤 컨테이너에 대해 알아본다.


1. 웹 애플리케이션과 싱글톤의 필요성

 스프링 없는 순수한 DI 컨테이너인 AppConfig는 요청을 할 때마다 객체를 새로 생성한다. 만약 고객 트래픽이 초당 100회 발생한다면, 초당 100개의 서비스 객체가 생성되고 소멸되어야 한다. 이는 심각한 메모리 낭비를 초래한다.

 

 이 문제를 해결하기 위해 해당 객체가 딱 1개만 생성되고, 이를 공유하도록 설계하는 것이 바로 싱글톤 패턴(Singleton Pattern)이다.


2. 스프링 컨테이너: 싱글톤 레지스트리

 직접 자바 코드로 싱글톤 패턴을 구현하려면 코드 자체가 복잡해지고, DIP/OCP 원칙 위반, 테스트의 어려움 등 수많은 단점이 발생한다. 스프링 컨테이너는 이러한 싱글톤 패턴의 문제점을 해결하면서 객체 인스턴스를 싱글톤으로 관리한다.

  • 싱글톤 레지스트리: 스프링 컨테이너는 별도의 싱글톤 패턴 코드를 추가하지 않아도 빈을 하나만 생성하여 관리한다.
  • 장점: 지저분한 싱글톤 구현 코드 없이도 성능 최적화를 누릴 수 있으며, 프레임워크의 제약 없이 유연하게 객체를 설계할 수 있다.

3. 싱글톤 방식의 주의점: 무상태(Stateless) 설계

 싱글톤 객체는 여러 클라이언트가 하나의 같은 인스턴스를 공유하기 때문에, 절대로 상태를 유지(Stateful)하게 설계하면 안 된다. 특정 클라이언트가 값을 변경할 수 있는 필드가 존재할 경우, 다른 클라이언트의 데이터가 오염되는 대형 장애가 발생할 수 있기 때문이다.

public class StatefulService {
    private int price; // 상태를 유지하는 공유 필드

    public void order(String name, int price) {
        this.price = price; // 여기서 문제가 발생한다!
    }

    public int getPrice() {
        return price;
    }
}

해결 방안: 필드 대신 지역변수, 파라미터, ThreadLocal 등을 사용하여 공유되지 않는 방식으로 데이터를 처리해야 한다. 스프링 빈은 항상 무상태(Stateless)로 설계해야 함을 명심해야 한다.


4. @Configuration과 바이트코드 조작의 마법

AppConfig 코드를 보면 의구심이 생길 수 있다.

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

 memberService를 만들 때 한 번, orderService를 만들 때 한 번, 총 두 번 memberRepository()가 호출되어 싱글톤이 깨지는 것처럼 보인다. 하지만 실제 테스트 결과는 모두 동일한 인스턴스를 참조한다.

 

 그 비밀은 @Configuration에 있다. 스프링은 클래스의 바이트코드를 조작하는 CGLIB 라이브러리를 사용하여 우리가 만든 AppConfig를 상속받은 가짜 프록시 객체를 생성한다.

CGLIB 프록시의 동작 (가상 코드)

@Bean
public MemberRepository memberRepository() {
    if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있으면?) {
        return 스프링 컨테이너에서 찾아서 반환;
    } else {
        기존 로직을 호출해서 생성 후 컨테이너에 등록;
        return 반환;
    }
}

 이 기술 덕분에 자바 코드상으로는 여러 번 호출되는 것처럼 보여도, 실제로는 컨테이너에 등록된 기존 빈을 반환하여 싱글톤을 보장하게 된다. 만약 @Configuration 없이 @Bean만 사용한다면, 스프링 빈으로는 등록되지만 이와 같은 싱글톤 보장 기능은 사라지게 된다.


결론: 싱글톤은 스프링의 근간

 스프링 컨테이너는 대규모 기업용 서비스를 지원하기 위해 탄생했으며, 그 핵심에는 효율적인 자원 관리를 위한 싱글톤 방식이 자리 잡고 있다. 개발자는 싱글톤의 공유 필드 문제를 항상 경계하고, 컨테이너가 제공하는 메커니즘을 신뢰하며 무상태 설계를 지향해야 한다.

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

[Basic-7] 의존관계 자동 주입의 전략과 빈 충돌 해결  (0) 2025.12.30
[Basic-6] 컴포넌트 스캔과 자동 의존관계 주입  (0) 2025.12.30
[Basic-4] 스프링 컨테이너의 생성과 빈 관리 메커니즘  (0) 2025.12.30
[Basic-3] 관심사의 분리와 의존관계 주입(DI)  (0) 2025.12.30
[Basic-2] 순수 자바 예제로 이해하는 DIP와 OCP 위반  (0) 2025.12.30
'Spring/Core' 카테고리의 다른 글
  • [Basic-7] 의존관계 자동 주입의 전략과 빈 충돌 해결
  • [Basic-6] 컴포넌트 스캔과 자동 의존관계 주입
  • [Basic-4] 스프링 컨테이너의 생성과 빈 관리 메커니즘
  • [Basic-3] 관심사의 분리와 의존관계 주입(DI)
h6bro
h6bro
백엔드 개발자의 기술 블로그
  • h6bro
    Jun's Tech Blog
    h6bro
  • 전체
    오늘
    어제
    • 분류 전체보기 (250) N
      • Java (18)
        • Core (9)
        • Design Pattern (9)
      • Spring (80)
        • Core (24)
        • MVC (6)
        • DB (10)
        • JPA (26)
        • Monitoring (3)
        • Security (11)
        • WebSocket (0)
      • Database (33)
        • Redis (15)
        • MySQL (18)
      • MSA (25) N
        • MSA 기본 (11)
        • MSA 아키텍처 (14) N
      • Kafka (30) N
        • Core (18) N
        • Connect (12)
      • ElasticSearch (11)
        • Search (11)
        • Logging (0)
      • Test (4)
        • k6 (4)
      • Docker (9)
      • CI&CD (10)
        • GitHub Actions (6)
        • ArgoCD (4)
      • Kubernetes (18)
        • Core (12)
        • Ops (6)
      • Cloud Engineering (4)
        • AWS Infrastructure (3)
        • AWS EKS (1)
        • Terraform (0)
      • Project (8)
        • LinkFolio (1)
        • Secondhand Market (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • Cloud Engineering 포스팅 정리
  • 인기 글

  • 태그

    ㅈ
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
h6bro
[Basic-5] 싱글톤 컨테이너와 CGLIB의 동작 원리
상단으로

티스토리툴바