본문 바로가기

카테고리 없음

싱글톤 패턴 이란? (Singleton Pattern)

객체지향의 디자인 패턴 중에서 아주 많이 들어봄 직하고, 비교적 간단한 패턴인 Singletone에 대해서 알아보겠습니다.

Single 이라는 말 그대로, 하나의 인스턴스를 가지는 패턴을 의미합니다. 

디자인 패턴은 결국 어떠한 상황/문제를 해결하고 유지보수 하는데 효율적인 패턴의 한 형태입니다. 

 

싱글톤은 언제, 왜 필요한가?

한 사람만, 카메라 접근이 가능한 경우

 

위 그림에서 처럼, 3명의 사람이 동시에 카메라를 사용할 수 없고, 1명씩만 사용해야하는 경우를 생각해봅시다.

실제 컴퓨팅 환경에서도 특정 앱(프로세스)이 PC Cam을 사용하고 있을때 다른 앱은 접근이 제하는 되는것이 일반적입니다.

 

그 외에도 생각보다 많습니다.

DB Connection pool의 경우 프로그램에서 여러개의 Connection을 만들고 프로세스는 1개의 연결을 관리 합니다. 

더 예를 든다면

  • 로그 관리 ( Logging ) : 어플리케이션 전반에 걸친 로그를 관리하는 인스턴스는 일반적으로 싱글톤으로 관리합니다.
  • 구성관리 ( Configuration ) : 어플리케이션 설정관리의 경우도 중앙에서 관리하도록 하려고 싱글톤을 사용합니다.
  • 세션 관리 ( Session ) : 세션 관리하는 매니저는 중복 생성을 피해야하므로, 싱글 톤으로 구현합니다.
  • 하드드웨어 인터페이스 엑세스 (  Hardware Interface Access ) : 하드웨어의 경우 중복접근을 방지해야 합니다.

 

싱글톤 패턴 구현 방법

  • 기본 생성자를 private 으로 생성하여, 외부에서 직접 생성을 방지합니다.
  • 사용자에게 생성된 인스턴스를 제공할 static 메소드가 있습니다.

 

기본 프로그램 예제

package Singleton;

public class Singleton {
    // 유일한 인스턴스를 저장할 변수
    private static Singleton instance;

    // 생성자를 private으로 선언하여 외부에서의 인스턴스화를 방지
    private Singleton() {}

    // 인스턴스에 접근할 수 있는 글로벌 접근 지점
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

 

위 코드는 Thread-Safe 문제가 있습니다.

만약 프로그램이 멀티 스레드로 동작하게 되면, getInstance( )를 했을때 if (instance == null)에서 동시에 null을 인식해서 2개의 인스턴스가 생성 될 수 있습니다.

이런 경우 어떻게 할까요? 바로 Java에서 synchronized 키워드를 사용합니다. 

 

Synchronized 활용

package Singleton;

public class Singleton {
    
    private static Singleton instance;

    private Singleton() {}

    // synchronized로 멀티 스레드 환경의 동시성 보장
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
 

이제 멀티 스레드에서 문제는 해결되었습니다.

하지만, synchronized 키워드는 선능이 저하됩니다. 그 전보다 대략 100배 정도 느려진다고 합니다. 

그렇다면 성능문제를 해결하면서 멀티 스레드 문제를 해결 할수 없을까요?  이중 잠금 체크 ( double-checked locking ) 패턴을 활용합니다.

 

double-checked Locking 활용

package Singleton;

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;
    }
}

인스턴스가 생성되어 있는지 체크하고, 생성이 안되었으면 동기화를 수행합니다.

'volatile' 키워드는 빈번하게 변경되고, 그 변경이 다른 스레드에 즉각으로  변경합니다.