A day without laughter is a day wasted.

코딩/디자인패턴

1. 싱글톤 패턴(Singleton pattern)의 개념과 구현 및 예시

민초쿠키칩 2025. 1. 3. 08:00

1. 싱글톤 패턴의 정의

싱글톤 패턴은 특정 클래스의 인스턴스를 하나만 생성하고, 이를 전역적으로 접근할 수 있도록 제공하는 디자인 패턴입니다.

 

 

2. 싱글톤 패턴을 사용하는 이유

    • 하나의 인스턴스만 필요할 때
      특정 클래스가 여러 개의 인스턴스를 가질 필요가 없고, 공유 자원이나 글로벌 설정 정보를 관리하는 경우 유용합니다.
    • 자원의 낭비 방지
      객체를 여러 개 생성하는 것은 메모리와 CPU 자원을 소모하므로, 하나의 인스턴스를 공유함으로써 자원을 절약합니다.
    • 전역 상태 관리
      애플리케이션의 설정, 로깅, 데이터베이스 연결 등 공유된 상태를 관리하는 데 적합합니다.

      쉽게 설명하면
    • 싱글톤 패턴은 "딱 하나의 물건(인스턴스)만 만들고, 모두가 그걸 공유해서 쓰게 하겠다"는 약속입니다.
      왜? 자원을 절약하고, 하나의 상태를 유지하기 위해서요.

현실 비유로는 커피 머신이 집에 하나밖에 없다고 생각해보세요. 가족 모두가 그 하나의 커피 머신을 공유해서 사용하는 거예요.굳이 여러 대의 커피 머신을 살 필요가 없죠.

 

3. 싱글톤 패턴을 사용하는 상황

  1. 로그(Log) 관리
    로그를 기록하는 클래스는 시스템 전역에서 하나의 인스턴스만 필요합니다.
  2. 설정(Configuration) 관리
    애플리케이션의 환경 설정 정보를 관리할 때 사용됩니다.
  3. 데이터베이스 연결 관리
    데이터베이스 연결 풀(Connection Pool)을 관리하는 데 사용합니다.
  4. 캐시(Cache) 관리
    자주 사용되는 데이터를 메모리에 캐싱하고 공유할 때 사용합니다.
  5. 스레드 관리
    스레드 풀(Thread Pool)처럼 공유되는 리소스를 관리할 때 사용됩니다.

 

 

4. 자바로 싱글톤 패턴 구현하기


(1) 싱글톤 패턴 기본 구현

public class Singleton {
    // 클래스 내부에 단일 인스턴스를 static으로 선언
    private static Singleton instance;

    // 생성자를 private으로 설정하여 외부에서 new 키워드로 인스턴스 생성 불가능
    private Singleton() {
        System.out.println("Singleton Instance Created!");
    }

    // public 메서드를 통해 인스턴스를 제공
    public static Singleton getInstance() {
        if (instance == null) { // 최초 호출 시에만 인스턴스를 생성
            instance = new Singleton();
        }
        return instance;
    }
}

 

(2) 사용 방법

public class Main {
    public static void main(String[] args) {
        // 싱글톤 인스턴스 가져오기
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        // 동일한 인스턴스인지 확인
        System.out.println(singleton1 == singleton2); // true
    }
}

 

5. 개선된 싱글톤 패턴

(1) 멀티스레드 환경에서의 문제

위 기본 구현은 멀티스레드 환경에서 안전하지 않습니다.

  • 두 개 이상의 스레드가 동시에 getInstance()를 호출하면, 인스턴스가 두 번 생성될 수 있습니다.

(2) 해결 방법: 스레드 안전한 싱글톤 구현

방법 : 동기화 (Synchronized)

public class Singleton {
    private static Singleton instance;
	private static Object _locking = new Object();
    
    private Singleton() { }

     public static Singleton getInstance() {
        // 첫 번째 검사
        if (instance == null) {
            synchronized (_locking) { // 잠금 
                // 두 번째 검사
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
 

위 코드는 DCL(Double-Checked Locking, 이중 검사 잠금) 기법을 활용하여 멀티스레드 환경에서 안전하게 싱글톤 인스턴스를 생성하는 방식입니다.

 

DCL(Double-Checked Locking)의 핵심 원리

  1. 첫 번째 검사 (if (instance == null))
    • 이미 인스턴스가 생성되어 있다면, 굳이 synchronized 블록에 들어가지 않습니다.
    • 이렇게 하면 불필요한 성능 저하를 방지할 수 있습니다.
  2. 두 번째 검사 (if (instance == null) 내부)
    • synchronized 블록 안에서 다시 _instance == null인지 확인합니다.
    • 이는 여러 스레드가 동시에 첫 번째 검사를 통과했을 때, 중복된 인스턴스 생성을 방지하기 위해 필요합니다.
  3. synchronized 키워드
    • 특정 스레드가 synchronized 블록 안으로 들어가면 다른 스레드는 대기하게 됩니다.
    • 이렇게 하면 인스턴스 생성 과정이 여러 스레드에 의해 중복 실행되지 않도록 보장합니다.
반응형