싱글톤 패턴은 객체의 인스턴스가 오직 1개만 생성되는 패턴을 의미합니다. 

 

구현

public class Singleton {

    private static Singleton instance = new Singleton();
    
    private Singleton() {
        // 생성자는 외부에서 호출못하게 private 으로 지정해야 한다.
    }

    // 1. Eager Initailization
    public static Singleton getInstance() {
        return instance;
    }
    
    // 2. Lazy Initailization
    public static synchronzied Singleton getInstance() {
      if(uniqueInstance == null) {
         uniqueInstance = new Singleton();
      }
      return uniqueInstance;
    }
    
    // 3. Lazy Initialization. DCL
    public static Singleton getInstance() {
      if(uniqueInstance == null) {
         synchronized(Singleton.class) {
            if(uniqueInstance == null) {
               uniqueInstance = new Singleton(); 
            }
         }
      }
      return uniqueInstance;
    }
}

싱글톤 패턴의 특징은 두가지가 있습니다.

  1. private 생성자
  2. static method

private 생성자는 외부에서 객체를 생성할 수 없도록하기위해 사용합니다. (객체를 오직 한번만 생성하도록)
static 키워드의 특징을 이용해서 클래스 로더가 초기화 하는 시점에서 정적 바인딩(static binding)을 통해 해당 인스턴스를 메모리에 등록해서 사용하는 것 입니다. 

 

 

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

  1. 메모리 측면
    • 최초 한번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 해당 객체에 접근할 때 사용되는 메모리 낭비를 방지할 수 있습니다.
  2. 쉬운 데이터 공유
    • 싱글톤 인스턴스는 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있습니다.
    • 하지만, 여러 클래스의 인스턴스에서 싱글톤 인스턴스의 데이터에 동시에 접근하게 되면 동시성 문제가 발생할 수 있으니 유의하여 설계해야 합니다.

 

 

싱글톤 패턴의 문제점

  1. 싱글톤 패턴을 구현하는 코드 자체가 많이 필요합니다.
    • 앞서 소개한 구현 방법외에도 정적 팩토리 메서드에서 객체 생성을 확인하고 생성자를 호출하는 경우에 멀티스레딩 환경에서 발생할 수 있는 동시성 문제 해결을 위해 syncronized 키워드를 사용해야 합니다
  2. 테스트하기 어렵다.
    • 싱글톤 인스턴스는 자원을 공유하고 있기 때문에 테스트가 결정적으로 격리된 환경에서 수행되려면 매번 인스턴스의 상태를 초기화시켜주어야 합니다. 그렇지 않으면 애플리케이션 전역에서 상태를 공유하기 때문에 테스트가 온전하게 수행되지 못합니다.
  3. 의존 관계상 클라이언트가 구체 클래스에 의존합니다.
    • new 키워드를 직접 사용하여 클래스 안에서 객체를 생성하고 있으므로, 이는 SOLID 원칙 중 DIP (의존관계역전)를 위반하게 되고 OCP (개방-폐쇄)원칙 또한 위반할 가능성이 높다.   => 스프링에서는 빈 컨테이너를 통해 해결합니다.

+ Recent posts