싱글톤 패턴과 스프링의 싱글톤 관리

2025. 4. 30. 16:06·SpringBoot

수동 DI(Dependency Injection)의 문제

객체를 필요할 때 직접 생성하면,
계속 새로운 인스턴스가 생성되어 메모리 낭비와 일관성 문제가 발생한다.


OrderService.java (문제 버전)

public class OrderService {
    private PaymentProcessor paymentProcessor;

    public OrderService() {
        // 필요한 시점마다 새로 객체를 생성
        this.paymentProcessor = new PaypalProcessor();
    }

    public void checkout(Order order) {
        paymentProcessor.processPayment(order.getTotalAmount());
    }
}

OrderService 생성 시마다 PaypalProcessor 새 인스턴스 생성


Main.java

public class Main {
    public static void main(String[] args) {
        OrderService service1 = new OrderService();
        OrderService service2 = new OrderService();

        System.out.println(service1.paymentProcessor == service2.paymentProcessor); // false
    }
}

service1과 service2의 paymentProcessor는 서로 다른 객체 → 불필요한 메모리 낭비!


문제를 해결하는 방법: 싱글톤 패턴

하나의 객체만 생성하고, 재사용하면 문제를 해결할 수 있다.
이를 위해 등장한 것이 전통적인 싱글톤 패턴


고전적인 싱글톤 구현 방법

Printer.java

public class Printer {
    private static final Printer instance = new Printer();

    // 외부에서 생성 못하게 private 생성자
    private Printer() {}

    // 유일한 인스턴스 제공
    public static Printer getInstance() {
        return instance;
    }

    public void print(String message) {
        System.out.println("출력: " + message);
    }
}

Printer 객체는 애플리케이션 전체에서 단 하나만 존재합니다.


Main.java

public class Main {
    public static void main(String[] args) {
        Printer printer1 = Printer.getInstance();
        Printer printer2 = Printer.getInstance();

        printer1.print("Hello");
        printer2.print("World");

        System.out.println(printer1 == printer2); // true
    }
}

printer1, printer2가 같은 인스턴스를 가리킵니다!


싱글톤 패턴의 한계

  • 코드가 복잡해짐 (private 생성자, static instance 관리)
  • 테스트 어려움 (싱글톤 객체가 테스트 간 상태를 공유할 수 있음)
  • DIP(의존 역전 원칙), OCP(개방-폐쇄 원칙) 위반 가능성
  • 유연성이 떨어져 확장 및 변경이 힘듦

특히 규모가 커질수록 관리가 어려워진다.


스프링 컨테이너: 싱글톤 문제를 자동으로 해결!

스프링은 컨테이너가 객체를 싱글톤으로 자동 관리한다.
개발자가 직접 싱글톤 코드를 작성할 필요가 없다.

  • 하나의 객체를 생성 → 모든 곳에 주입
  • 객체 생명주기를 스프링이 관리
  • 결합도 낮고 확장성 높은 아키텍처 구현 가능

스프링 싱글톤 Bean

Printer.java

import org.springframework.stereotype.Component;

@Component
public class Printer {
    public void print(String message) {
        System.out.println("출력: " + message);
    }
}

@Component를 붙이면 스프링이 자동으로 Bean으로 등록하고, 싱글톤으로 관리합니다.


AppConfig.java

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

Main.java (Spring Context 사용)

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        Printer printer1 = context.getBean(Printer.class);
        Printer printer2 = context.getBean(Printer.class);

        printer1.print("Hello Spring");
        printer2.print("Singleton Check");

        System.out.println(printer1 == printer2); // true
    }
}

printer1, printer2가 같은 객체 → 스프링이 자동으로 싱글톤 보장


만약 싱글톤이 아니게 하고 싶다면?

  • @Scope("prototype")을 사용하면 요청마다 새로운 객체를 생성합니다.
@Component
@Scope("prototype")
public class Printer {
    ...
}

기본은 싱글톤, 필요 시 프로토타입으로 설정 가능!


정리: 왜 스프링은 기본적으로 싱글톤을 사용할까?

이유 설명
성능 최적화 객체 생성을 최소화하여 메모리/CPU 절약
일관성 유지 동일 요청에 대해 항상 같은 객체 제공
관리 편의성 객체 생명주기 자동 관리, 개발자는 비즈니스 로직 집중

결론

  • 수동 DI를 하면 객체가 계속 생성되어 비효율 발생
  • 이를 막기 위해 고전적 싱글톤 패턴 등장
  • 그러나 코드 복잡성, 테스트 어려움 등 부작용 존재
  • 스프링은 컨테이너를 통해 자동으로 싱글톤을 보장하고, 관리 부담을 없앰
  • 개발자는 "비즈니스 로직"에만 집중할 수 있게 됨

'SpringBoot' 카테고리의 다른 글

스프링 DI: 생존자 주입을 권장하는 이유  (0) 2025.05.05
스프링 빈 자동 등록과 의존성 주입  (1) 2025.05.01
Spring Boot: 데이터 검증(Validation)  (1) 2024.11.22
Spring Boot: 로깅(Logging) 구현하기  (1) 2024.11.21
Spring Boot: @ExceptionHandler와 @ControllerAdvice를 활용한 예외처리  (0) 2024.11.20
'SpringBoot' 카테고리의 다른 글
  • 스프링 DI: 생존자 주입을 권장하는 이유
  • 스프링 빈 자동 등록과 의존성 주입
  • Spring Boot: 데이터 검증(Validation)
  • Spring Boot: 로깅(Logging) 구현하기
moodone
moodone
  • moodone
    무던하게
    moodone
  • 전체
    오늘
    어제
    • 분류 전체보기 (36)
      • Java (7)
      • SpringBoot (24)
      • JavaScript (0)
      • Database (1)
      • Python (0)
      • Git (1)
      • IDE (0)
      • 기타 (3)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    git
    git bash
    티스토리챌린지
    오블완
    Repository
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
moodone
싱글톤 패턴과 스프링의 싱글톤 관리
상단으로

티스토리툴바