본문 바로가기
📒 기술 또는 개념/🎨 Design Pattern

[Design Pattern] 싱글톤(Singleton) 패턴에 대해

by DEV_DAON 2023. 10. 23.

오늘은 디자인 패턴 중 생성 패턴의 싱글톤 패턴에 대해 알아보자!

 

싱글톤(Singleton) 패턴이란?

 

싱글톤 패턴은 인스턴스를 오직 1개만 생성하고 이를 리턴해주는 패턴이다.

Singleton Pattern

이러한 패턴은 주로 프로그램 내에서 하나로 공유를 해야 하는 객체가 존재할 때 해당 객체를 싱글톤으로 구현하여 모든 유저 또는 프로그램들이 해당 객체를 공유하며 사용하도록 할 때 사용된다.

 

즉, 싱글톤 패턴은 아래와 같은 상황에서 사용한다.

- 프로그램 내에서 하나의 객체만 존재해야 한다.

- 프로그램 내에서 여러 부분에 해당 객체를 공유하여 사용해야한다.

 

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

 

하나의 인스턴스만을 사용하는 싱글톤 패턴의 이점은 다음과 같다.

 

1. 메모리 측면의 이점 : 싱글톤 패턴을 사용하게 된다면 한 개의 인스턴스만을 고정 메모리 영역에 생성하고 추후 해당 객체를 접근할 때 메모리 낭비를 방지할 수 있다.

2. 속도 측면의 이점 : 생성된 인스턴스를 사용할 때는 이미 생성된 인스턴스를 활용하여 속도 측면에 이점이 있다.

3. 데이터 공유의 편의 : 전역으로 사용하는 인스턴스이기 때문에 다른 여러 클래스에서 데이터를 공유하며 사용할 수 있다. 하지만 동시성 문제가 발생할 수 있어 이 점은 유의해야 한다.

 

싱글톤 패턴 구현하기

public class Singleton {
    // 단 1개만 존재해야 하는 객체의 인스턴스로 static 으로 선언
    private static Singleton instance;

    // private 생성자로 외부에서 객체 생성을 막아야 한다.
    private Singleton() {
    }

    // 외부에서는 getInstance() 로 instance 를 반환
    public static Singleton getInstance() {
        // instance 가 null 일 때만 생성
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

싱글톤 패턴의 기본 구현 방법은 다음과 같다.

 

먼저 private static으로 Singleton 객체의 Instance를 선언하고 getInstance() 메서드가 처음 실행될 때만 하나의 instance가 생성되고 그 후에는 이미 생성된 instance를 return 하는 방식으로 진행된다.

 

여기서 핵심은 private로 된 기본 생성자이다. 생성자를 private로 생성하며 외부에서 새로운 객체의 생성을 막아줘야 한다.

// 같은 instance인지 Test
public class Application {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        System.out.println(singleton1);
        System.out.println(singleton2);
    }
}
        /** 출력
         * vendingmachine.Singleton@15db9742
         * vendingmachine.Singleton@15db9742
         **/

싱글톤 객체를 생성하는 위 코드를 실행해 보면 두 객체가 하나의 인스턴스를 사용하여 같은 주소 값을 출력하는 것을 확인할 수 있다.

 

Multi-thread에서의 싱글톤

 

Multi-thread환경에서 싱글톤을 사용하게 된다면 다음과 같은 문제가 발생할 수 있다.

 

1. 여러 개의 인스턴스 생성

Multi-thread환경에서 instance가 없을 때 동시에 아래의 getInstance() 메서드를 실행하는 경우 각각 새로운 instance를 생성할 수 있다.

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

 

2. 변수 값의 일관성 실패

다음과 같은 코드가 실행되었을 때, 여러 개의 thread에서 plusCount()를 동시에 실행한다면 일관되지 않은 값들이 생길 수 있다.

public class Singleton {
    private static Singleton instance;
    private static int count = 0;
    
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    public static void plusCount() {
        count++;
    }
}

 

이제 해결법에 대해 알아보자!

 

1. 정적 변수 선언에서 인스턴스 생성

이러한 문제는 static 변수로 singleton 인스턴스를 생성하는 방법으로 해결할 수 있다.

아래와 같이 초기에 인스턴스를 생성하게 된다면 Multi-thread 환경에서도 다른 객체들은 getInstance를 통해 하나의 인스턴스를 공유할 수 있다.

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

    private Singleton() {
    }

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

 

2. synchronzied의 사용

synchronized를 적용하여 Multi-thread환경에서의 동시성 문제를 해결하는 방법이다.

하지만 이 방법은 Thread-safe를 보장하기 위해 성능 저하가 발생할 수 있다.

(여기서 Thread-safe란 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없는 것을 말한다.)

public class Singleton {
    public class Singleton {
        private static Singleton instance;

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

 

싱글톤 패턴은 메모리, 속도, 데이터 공유 측면에서 이점을 가지고 있다. 다만 그렇다고 해서 싱글톤 패턴이 무조건 좋은 것은 결코 아니다.

Multi-thread환경에서는 동시성 문제가 발생할 수 있기에 싱글톤 패턴을 사용하고자 한다면 사용하기 앞서 "해당 객체의 인스턴스가 한 개만 존재하여야 하는지?" 여부와 "사용을 하였을 때 동시성 문제가 발생하지 않는지"를 생각하고 확인하며 사용해야 한다!

 

참고

https://velog.io/@seongwon97/%EC%8B%B1%EA%B8%80%ED%86%A4Singleton-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80

 

싱글톤(Singleton) 패턴이란?

싱글톤 패턴은 객체의 인스턴스를 한개만 생성되게 하는 패턴입니다.

velog.io