본문 바로가기

C#

싱글톤 패턴(Singleton Pattern)

728x90

싱글톤 패턴(Singleton Pattern)이란?
싱글톤 패턴은 런타임 동안 단 하나의 인스턴스만을 생성하는 패턴을 의미한다. 싱글톤 패턴이 적용된 객체는 하나의 인스턴스만 생성할 수 있으며 다른 객체에서 싱글톤 객체의 인스턴스를 생성하려 할 경우 기존에 생성된 인스턴스가 있다면 해당 인스턴스를 반환하는 형태이다.

싱글톤 패턴의 장점
1. 메모리 절약과 성능 향상
   - 만약 많은 클래스에서 동일한 객체의 인스턴스를 생성해야 하는 경우, 싱글톤 패턴을 적용하지 않았다면 사용할 때마다 인스턴스가 생성된다. 물론 어지간해서는 인스턴스를 많이 생성했다고 성능이 저하되는 일은 드물지만 프로젝트의 규모가 크거나 성능이 중요시되는 프로젝트에서는 싱글톤 패턴을 사용하면 큰 도움이 된다.
2. 데이터 관리의 측면에서 유리
   - 하나의 인스턴스만 존재한다는 것은 인스턴스내에 있는 데이터의 관리도 그 곳에서만 하면 된다는 뜻이다. 예를 들어, 어떤 게임에서의 플레이어 점수를 관리하기 위해서는 점수를 관리하는 객체의 인스턴스 내에서 관리를 할 것이다. 싱글톤 패턴을 사용하지 않고 이를 구현하기 위해서는, static 클래스를 생성하거나 생성했던 인스턴스를 계속 유지해야 할 것이다. 이는 코드의 품질도 낮출뿐더러 객체지향 프로그래밍 관점에서 바람직한 방법이 아니므로 해당 방법보다는 싱글톤 패턴을 적용하는 것이 바람직하다.

싱글톤 패턴의 문제점
1. 정적 메모리에 할당된 객체로 해당 객체에 너무 큰 메모리가 쌓이게 되면 프로그램 성능이 현저하게 낮아질 수 있다. 이는 정적 메모리에 할당할 수 있는 메모리 크기가 제한적이기 때문이다.
2. 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유시킬 경우 다른 클래스의 인스턴스들 간에 결합도가 높아져 "개방-폐쇄 원칙"을 위배하게 된다(-> 객체 지향 설계 원치게 어긋남). 따라서 수정이 어려워지고 테스트하기 어려워진다.
3. 하나의 정적 메모리를 사용하기 때문에 병렬처리나 동기화와 같이 여러방법으로 메모리에 접근하는데 문제가 생기게 된다.(멀티쓰레드 환경에서 동기화처리를 안 하면 인스턴스가 두 개가 생성된다든지 하는 경우가 발생할 수 있음)

싱글톤 패턴 구현 방법(https://csharpindepth.com/Articles/Singleton)
- 여러가지가 있지만 Lazy 싱글톤 적용 : 인스턴스의 생성 시기를 선언 즉시 생성이 아니라 인스턴스 내에 있는 값을 접근하려 할 때 생성시켜주는 방법으로 보다 효율적으로 사용할 수 있다. 또한 일반적인 싱글톤에서는 thread-safety를 추가적으로 고려해야 하지만 Lazy 싱글톤을 사용하면 이를 고려하지 않아도 보장된다는 장점이 있다. (Lazy 싱글톤을 이요한 thread-safety 보장은 인스턴스의 생성에 대한 thread-safety를 보장하는 것이지 이미 생성된 인스턴스의 접근에 대한 보장이 아님.)

public class SingletonLazy<T> where T : SingletonLazy<T>, new() // 제너릭 형식 제약조건(옵션)
{
    private static Lazy<T> lazyInstance = null;

    public static T Instance
    {
        get
        {
            if (Exists() == false)
            {
                var instance = new T();
                lazyInstance = new Lazy<T>(() => instance);
            }

            return lazyInstance.Value;
        }
    }
    
    // 인스턴스가 만들어졌는지 체크합니다.
    public static bool Exists()
    {
        return lazyInstance != null && lazyInstance.IsValueCreated;
    }
    
    // 인스턴스 생성이력을 초기화 할때 사용합니다.
    public static void ClearInstance()
    {
        lazyInstance = null;
    }
}

 

[출처]
https://math-development-geometry.tistory.com/58
https://jeong-pro.tistory.com/m/86
https://morit.tistory.com/5

728x90

'C#' 카테고리의 다른 글

AutoMapper란?  (0) 2023.11.03
LiteDB  (0) 2023.01.31
구조체(struct)와 클래스(class)의 차이  (0) 2023.01.30
디자인 패턴 정의와 종류에 대해  (0) 2023.01.26
IoC(Inversion of Control; 종속성 반전)  (0) 2023.01.26