Singleton Pattern(싱글톤 패턴)

청포도봉봉이·2024년 4월 11일
1

디자인 패턴

목록 보기
2/2
post-thumbnail

싱글톤 패턴은 애플리케이션 전체에서 단 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴입니다. 싱글톤 클래스 자체가 인스턴스를 만들고 관리하며, 전역 액세스 지점을 제공합니다. 자바에서 싱글톤 패턴을 구현하는 방법은 다음과 같습니다.

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

이 코드에서 Singleton 클래스는 다음과 같은 특징을 가집니다.

  1. instance 변수는 클래스의 단일 인스턴스를 저장하는 정적(static) 변수입니다.
  2. 생성자는 private이므로 외부에서 직접 인스턴스화할 수 없습니다.
  3. getInstance() 메소드는 인스턴스를 반환하며, 인스턴스가 없으면 새로 생성합니다.

장점

  • 전역 상태를 관리하기 쉽습니다.
  • 메모리 사용량을 최소화할 수 있습니다.
  • 객체 초기화 비용을 절감할 수 있습니다.

단점

  • 단일 인스턴스를 공유하므로, 상태 변경 시 주의가 필요합니다.
  • 테스트하기 어려울 수 있습니다.
  • 싱글톤 인스턴스에 대한 글로벌 액세스 때문에 객체 지향 설계 원칙을 위반할 수 있습니다.

동시성 문제

멀티스레드 환경에서 동시성 문제가 발생할 수 있습니다. 위 코드에서 여러 스레드가 동시에 getInstance() 메소드를 호출하면, 두 개 이상의 인스턴스가 생성될 수 있습니다. 이를 해결하기 위해서는 동기화가 필요합니다.

동시성 문제 해결

1. 이른 초기화(Eager Initialization)

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

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

클래스 로딩 시점에 인스턴스를 생성하므로 동기화 문제가 발생하지 않습니다. 하지만 싱글톤 객체가 필요하지 않더라도 항상 인스턴스를 생성하므로 리소스 낭비가 있을 수 있습니다.

2. 동기화된 getInstance() 메소드

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

getInstance() 메소드에 synchronized 키워드를 추가하여 동기화를 보장합니다. 하지만 이 방식은 성능 저하가 발생할 수 있습니다.

3. 이중 검사 잠금(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;
    }
}

이 방식은 동기화 블록을 최소화하여 성능을 개선합니다. 첫 번째 if 문에서 인스턴스가 없는 경우에만 동기화 블록을 실행합니다. volatile 키워드는 인스턴스 변수의 최신 상태를 보장합니다.

4. 정적 내부 클래스(Static Inner Class)

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

    private Singleton() {}

    public static Singleton getInstance() {
        return SingletonHelper.instance;
    }
}

이 방식은 클래스 로딩 시점에 인스턴스를 생성하지만, 실제로 getInstance()가 호출될 때까지 인스턴스를 생성하지 않습니다. 동기화 문제도 없고, 리소스 낭비도 없습니다.

5. Enum 싱글톤

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        // ...
    }
}

Java 5 이후 버전에서는 enum을 사용하여 싱글톤 패턴을 구현할 수 있습니다. 이 방식은 Thread-safe하고 직렬화가 가능하며, 리플렉션에 대한 보안성이 높습니다.

요약하면, 싱글톤 패턴은 애플리케이션 전체에서 단 하나의 인스턴스만 존재하도록 보장합니다. 장점과 단점이 있으며, 동시성 문제를 해결하기 위해 여러 가지 방법이 있습니다. 상황에 따라 적절한 방법을 선택하여 사용해야 합니다.

profile
서버 백엔드 개발자

0개의 댓글