Back_End/JAVA

싱글톤 패턴 (Singleton Pattern)

10Biliion 2025. 2. 13. 08:37

 

 

 

1. 싱글톤 패턴이란?

싱글톤 패턴(Singleton Pattern)은 어떤 클래스가 오직 하나의 인스턴스만 가지도록 보장하는 디자인 패턴이다. 이는 전역 상태를 관리하거나, 공통 리소스를 공유해야 할 때 유용하다.

사용 목적

  • 객체 생성 비용 절감
  • 전역 상태 유지
  • 하나의 인스턴스를 여러 곳에서 공유

2. 싱글톤 패턴 구현 방법

싱글톤 패턴을 구현하는 방법에는 여러 가지가 있으며, 각 방식마다 장단점이 있다.

2.1 기본적인 싱글톤 (Eager Initialization)

public class Singleton {
    private static final Singleton instance = new Singleton();
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        return instance;
    }
}

✅ 장점

  • 구현이 간단함
  • 클래스 로딩 시점에 객체가 생성되어 이후 호출 속도가 빠름

❌ 단점

  • 객체가 필요하지 않아도 미리 생성됨 (리소스 낭비 가능)

2.2 지연 초기화 (Lazy Initialization)

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

✅ 장점

  • 객체가 필요할 때만 생성됨 (리소스 절약 가능)

❌ 단점

  • 멀티스레드 환경에서 안전하지 않음 (동시에 여러 개의 인스턴스가 생성될 위험)

2.3 동기화된 싱글톤 (Thread-safe Lazy Initialization)

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

✅ 장점

  • 멀티스레드 환경에서 안전함

❌ 단점

  • synchronized 사용으로 성능 저하 가능

2.4 Double-Checked Locking (이중 체크 잠금)

public class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

✅ 장점

  • 멀티스레드 환경에서도 안전하며, 동기화 비용을 최소화

❌ 단점

  • 코드가 복잡해질 수 있음

2.5 정적 내부 클래스 (Bill Pugh Singleton)

public class Singleton {
    private Singleton() {}
    
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

✅ 장점

  • Lazy Initialization을 보장하면서도 Thread-safe함
  • 동기화 없이 빠른 속도 제공

❌ 단점

  • 복잡해 보일 수 있음

2.6 Enum 싱글톤

public enum Singleton {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("싱글톤 동작");
    }
}

✅ 장점

  • 가장 간단하면서도 멀티스레드에서 안전
  • 직렬화/역직렬화 문제 자동 해결

❌ 단점

  • Enum을 상속할 수 없음 (다른 클래스를 확장해야 하는 경우 사용 불가)

3. 정리 및 추천

방법 Lazy Initialization Thread-safe 성능 추천 여부
기본 싱글톤 X
지연 초기화 X
동기화된 싱글톤 X
Double-Checked Locking O
정적 내부 클래스 ✅ (가장 추천)
Enum O (특정 상황에서 추천)

가장 추천하는 방법은 정적 내부 클래스 방식이다. 하지만, Enum 방식은 직렬화가 필요하거나 가장 간단한 방법을 원할 때 좋은 선택이 될 수 있다.