싱글톤 패턴이란?
오직 하나의 인스턴스만 생성되도록 보장하고,
그 인스턴스에 전역적으로 접근할 수 있도록 하는 패턴이다.
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
private으로 생성자 접근을 막고, 정적 메소드 팩토리로 만들면 그게 싱글톤인가요? 🙋🏻♀️ (모양이 비슷해서..)
NO ❌
싱글톤은 항상 같은 인스턴스를 반환한다.
싱글톤 패턴은 아래의 2가지를 지켜야한다.
- 생성자를 외부에서 못 부르게 한다 (private)
- 항상 같은 인스턴스를 반환한다
( 생성자 private + 정적 메소드 팩토리 )를 사용하면 1번은 지킬 수 있지만, 아래와 같이 매번 new 인스턴스를 생성해서 반환한다면 2번에 위배된다.
public class User {
private User() {}
public static User create() {
return new User(); // 매번 새 객체
}
}
싱글톤의 장단점
장점 : 인스턴스 하나로 공유하므로, 공통 상태 관리에 용이하다.
→ DB 커넥션 풀, Thread pool 등 절약
단점 : TDD에 불편하다.
→ 테스트들 간의 인스턴스를 하나로 공유하므로, 테스트 순서에 따라 테스트 결과가 바뀔 수 있다.
자바 싱글톤 구현 방식은?
1) 정적 맴버와 중첩 클래스 방식 (Eager Initializtion vs Lazy Initializtion)
싱글톤 패턴 구현 방식에도 종류가 있다.
위에는 정적 맴버로 싱글톤을 구현하여 Eager Initialization(즉시 초기화)하는 방식이고,
아래는 중접 클래스로 싱글톤을 구현해 Lazy Initialization하는 방식이다.
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
public class Singleton {
private static class SingleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingleInstanceHolder.INSTANCE;
}
}
2) DCL (이중잠금) 방식 싱글톤
DCL (이중잠금) 방식으로도 싱글톤을 구현할 수 있다.
DCL은 synchronized 비용을 줄이기 위해 고안된 thread-safe 싱글톤 구현 방식이다.
@Component // Spring에서도 관리하게 할 수는 있음 (권장 X)
public class DclSingleton {
// 🔑 반드시 volatile
private static volatile DclSingleton instance;
private DclSingleton() {
}
public static DclSingleton getInstance() {
// 1️⃣ 첫 번째 체크 (락 없이)
if (instance == null) {
synchronized (DclSingleton.class) {
// 2️⃣ 두 번째 체크 (락 안에서)
if (instance == null) {
instance = new DclSingleton();
}
}
}
return instance;
}
}
*메인 메모리에서 값을 저장하고 읽어오기 위해 반드시 volatile 키워드를 사용해야한다.
그러면 DCL 방식 싱글톤은 언제 사용하나요?
JVM 레벨 라이브러리에서 사용하거나, 객체 생성 비용이 어마어마하게 클 때 사용한다. (Spring에서는 거의 사용하지 않음)
3) ENUM 방식 싱글톤
enum은 기본적으로 thread-safe 하기 때문에 enum으로 구현하기도 한다.
public enum Singleton {
INSTANCE;
public void doSomething() {
System.out.println("싱글톤 로직 실행");
}
}
스프링에서 싱글톤 패턴은?
자바에서 구현하는 싱글톤과 Spring에서 사용하는 싱글톤은 다르다.
별도로 싱글톤 패턴을 구현하지 않아도 스프링 컨테이너가 자동으로 단 하나의 인스턴스만 생성한다
Spring Container 안에서 하나의 Bean 인스턴스만 관리하기 때문에,
Spring 싱글톤은 디자인 패턴이라기보다 컨테이너 기능에 가깝다.
Spring은 싱글톤 빈은 Eager Initialization(즉시 초기화)를 기본으로 하고 있다.
그래야 초기 시작 과정에서 빠르게 오류를 확인할 수 있기 때문이다.
@Component
public class PaymentService {
public PaymentService() {
System.out.println("PaymentService 생성");
}
}

https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-lazy-init.html
Lazy-initialized Beans :: Spring Framework
By default, ApplicationContext implementations eagerly create and configure all singleton beans as part of the initialization process. Generally, this pre-instantiation is desirable, because errors in the configuration or surrounding environment are discov
docs.spring.io
만약, 이후에 초기화를 하고 싶다면 @Lazy를 사용하면된다.
해당 Bean이 처음 요청되는 시점에 생성된다.
@Component
@Lazy
public class HeavyService {
public HeavyService() {
System.out.println("HeavyService 생성");
}
}
스프링에서 빈이 싱글톤으로 관리되면, 하나의 빈을 사용하니까 동시성 문제에서도 안전한가요?
No ❌
Spring 싱글톤은 하나의 인스턴스를 보장할 뿐, thread-safe까지 보장하지는 않는다.
여러 요청이 동시에 들어오면, 여러 스레드가 하나의 싱글톤 Bean을 동시에 사용하게 된다.
그 결과, 상태를 가지는 싱글톤 Bean에서는 Race Condition과 같은 동시성 문제가 발생할 수 있다.
아래의 예시의 경우 한꺼번에 2번 요청이 들어올 때, 아래와 같이 잘못된 결과를 반환할 수 있다.
- Thread A: count = 0 → 1
- Thread B: count = 0 → 1
(2번 요청했으나 결과가 2가 아닌 1이 나옴)
@Component
public class CounterService {
private int count = 0;
public void increase() {
count++;
}
public int getCount() {
return count;
}
}
이를 위해서는 아래와 같이 Bean이 상태를 갖지 않게 하는 것이 좋다.
@Service
public class CounterService {
public int increase(int currentCount) {
return currentCount + 1;
}
}
질문 리스트
체크리스트를 답변해보며 내용이 이해가 되었는지 확인해보아요!
✅ 체크 리스트
1. Spring에서는 싱글톤을 어떻게 사용하는가?
2. 자바 싱글톤과 Spring 싱글톤의 차이점은 무엇인가?
3. Spring 싱글톤이면 무조건 thread-safe한가?
1. Spring에서는 싱글톤을 어떻게 사용하는가?
→ 개발자가 직접 싱글톤 패턴을 구현하지 않아도, Spring Container가 하나의 Bean 인스턴스를 생성·관리한다
2. 자바 싱글톤과 Spring 싱글톤의 차이점은 무엇인가?
→ 자바: 클래스가 직접 인스턴스 생성을 통제
→ Spring: 컨테이너가 객체 생명주기를 관리
3. Spring 싱글톤이면 무조건 thread-safe한가?
Spring 싱글톤 → 인스턴스가 하나임을 보장
Thread-safe→ 여러 스레드에서 안전하게 동작함을 보장
관련 면접 질문 정리 🧚🏻♀️
1. 싱글톤 패턴이란 무엇인가요?
2. 싱글톤의 장단점은 무엇인가요?
3. Spring에서 싱글톤은 어떻게 관리되나요?
'CS' 카테고리의 다른 글
| [CS] 동기화 문제: 똑같이 더하고 뺐는데 왜 sharedData는 0이 안 나올까? (Mutex, Semaphore) (0) | 2025.12.26 |
|---|---|
| [CS] 왜 HTTP 통신에는 직렬화가 필요할까? JSON과 Spring MVC로 이해하는 직렬화와 역직렬화 (0) | 2025.12.12 |