CS 스터디 15주차
싱글톤 패턴
싱글톤 패턴(Singleton Pattern)
싱글톤 패턴은 다양한 디자인 패턴 중 하나로 한 클래스에 대해서 단 하나의 인스턴스만 존재하도록 보장하는 패턴이다.
어플리케이션에서 전역으로 접근 가능한 인스턴스를 제공하여 상태나 행위를 공유할 때 유용하고,
주로 설정/로그/데이터베이스 연결 관리 등에서 사용한다.
특정 객체가 애플리케이션 전체에서 일관된 상태를 유지하면서 접근 가능해야하는 경우
(설정 관리나 로그 관리) 이 객체들이 동일한 상태를 유지해야 하기 때문에 전역적인 접근성이 좋다.
또한 데이터 베이스에 연결된 객체나 파일 시스템 접근 객체와 같이 비용이 큰 리소스를 관리해야 할 때
여러 개의 객체가 생성되는 것을 방지하여 리소스 절약에 효율적이며,
중요한 상태 정보를 유지하는 객체는 단 하나만 존재하도록 하기에 일관된 상태관리를 한다.
싱글톤 패턴(Singleton Pattern)의 기본 구현
JAVA
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
먼저 private static Singleton instance; 로 유일한 인스턴스를 저장 할 정적 변수를 하나 선언해준다.
이 변수에 대한 생성자를 private으로 선언하면 외부에서 더이상 인스턴스화를 할 수 없고,
메서드에서 인스턴스를 얻는 정적 메서드로 작성을 해준다.
getInstance()메서드를 호출할 때 인스턴스가 존재하지 않으면 새로 생성하고
만약 존재한다면 기존의 인스턴스를 반환하게 된다.
PYTHON
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 is singleton2)
파이썬에서 구현할 때도 자바와 비슷하다.
__new__ 메서드를 재정의하여 클래스의 인스턴스를 생성할 때 단 하나의 인스턴스만 생성이 되도록 해준다.
싱글톤 패턴(Singleton Pattern)의 장단점
장점
1. 애플리케이션 전역에서 접근 가능한 상태 또는 객체 관리가 된다.
2. 인스턴스를 하나만 생성하기 때문에 메모리나 리소스 절약이 된다.
3. 멀티스레드 환경에서 단일 인스턴스에 대한 동기화 접근 관리가 가능하다.
4. 인스턴스가 처음 필요해질 때 생성되도록 지연 초기화를 통해 객체의 초기화 시점 제어가 가능하다.
단점
1. 하나의 클래스에서 많은 역할을 담당하기 때문에 단일 책임 원칙에 위배되고 유지보수가 어려워진다.
2. 전역 인스턴스를 사용하기 때문에 단위 테스트가 어려울 수 있다.
3. 멀티스레드에서 사용하게 될 때 적절한 동기화 과정이 없다면 문제가 발생할 수 있다.
4. 상속이 어려워서 다형성에 제한이 걸린다.
실습
1. 애플리케이션 전역에서 로그를 기록하는 객체가 필요할 때
2. 데이터 베이스 연결관리
싱글톤 패턴(Singleton Pattern)에서의 동기화 과정
장단점에서 말했던 것처럼 만약 멀티스레드 환경에서 싱글톤 패턴을 구현하려면 어떻게 해야할까.
이 패턴을 안전하게 구현하기 위해서는 인스턴스가 여러 개 생성되지 않도록
동기화 처리를 해주어야 한다.
Java에서의 싱글톤 패턴을 동기화 하는 방법에 여러가지가 있지만 그 중 많이 사용되는 방법은
1. synchronized
2. 이중 검사 잠금
두 가지가 가장 많이 사용된다.
먼저 synchronized 키워드를 사용하여 메서드 전체를 동기화 할 경우 한 스레드가 이 메서드를 실행하는 동안
타 스레드는 해당 메서드를 실행할 수 없게 된다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
이 방법은 구현이 간단한 편이지만 해당 메서드가 호출될 때마다 동기화 처리가 계속 발생하기 때문에
성능 저하가 우려되며 특히 인스턴스가 이미 생성된 후에도 동기화 처리가 계속 필요하다.
성능 저하가 걱정될 때 사용할 수 있는 두번째 방법이 이중 검사 잠금 방법이다.
이 방법은 처음에 동기화를 하지 않은 채 인스턴스를 체크하고 필요한 경우에만 동기화를 적용한다.
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;
}
}
위 코드에서 instance 변수는 volatile로 선언했다.
volatile 키워드는 인스턴스 변수에 대한 읽기 및 쓰기 작업이 다른 스레드에 의해 가로막히지 않도록 보장하는 키워드로
이중 검사 잠금을 사용하면 인스턴스가 이미 생성된 경우 동기화 블록을 건너뛰므로 성능 저하가 줄어든다.
다음,Python에서의 싱글톤 패턴의 동기화는 threading 모듈을 사용할 수 있다.Python의 GIL(Global Interpreter Lock)은 단일 스레드에서 동기화 문제를 어느 정도 해결해주지만, 멀티스레드 환경에서는 명시적인 동기화가 필요한 경우도 있기 때문에 같이 정리해본다.
기본적인 동기화 방법은 threading.Lock을 사용한다.
import threading
class Singleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
위 코드에서는 with cls._lock 구문을 사용하여 동기화 블록을 생성하면 cls._lock이 잠긴 상태에서 인스턴스가 생성되며, 이 블록이 끝나면 자동으로 잠금이 해제되는 방식이다.이렇게 하면 여러 스레드가 동시에 인스턴스를 생성하려고 할 때, 첫 번째 스레드만 인스턴스를 생성하고 나머지는 이미 생성된 인스턴스를 반환하게 된다.
Python에서도 Java처럼 이중 잠금 사용이 가능한데,이 방식은 인스턴스가 생성된 경우에 동기화 블록을 건너뛰어서 성능 저하를 최소화 시킨다.
import threading
class Singleton:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
싱글톤 패턴은 특정 클래스의 인스턴스를 단 하나만 존재하도록 보장하여 전역 상태 관리와
리소스 절약을 가능하게 하는 유용한 디자인 패턴인 것을 알았다.
하지만 남용하면 코드의 유연성과 테스트 가능성을 저하시킬 수 있으므로, 필요할 때 적절히 사용하는 것이 중요하다고 생각되며
다양한 상황에서 싱글톤 패턴을 올바르게 적용하면 애플리케이션의 성능과 유지보수성을 높일 수 있을 것이다.
'🪄Interview > ✏️Study' 카테고리의 다른 글
[JavaScript Study] 1주차 - 구구단 구현하기1 (0) | 2024.08.17 |
---|---|
[CS STUDY INTERVIEW] 16주차 - 옵저버 패턴 & 스트레티지 패턴 & 컴포지트 패턴 (0) | 2024.07.16 |
[CS STUDY INTERVIEW] 14주차 - 팩토리 메서드 패턴 (0) | 2024.06.20 |
[CS STUDY INTERVIEW] 14주차 - 템플릿 메서드 패턴 (1) | 2024.06.19 |
[CS STUDY INTERVIEW] 13주차 - 어댑터 패턴 (0) | 2024.06.05 |