본문 바로가기
[개발] 이야기/[DotNet] 이야기

[C# 디자인패턴] Singleton패턴 정복하자(Lazy) - 더이상 암기하지 마세요

by 헤이나우
반응형

Singleton디자인 패턴은 하나의 클래스를 인스턴스화 할 때 무한히 생성되는 것이 아니라 하나의 인스턴스만 갖도록 제한하고, 프로그램의 전역 범위에서 그 인스턴스를 액세스 할 수 있는 패턴이다. 클래드 아이어 그램을 보게 되면 아래와 같다.

싱글톤 다이어그램
클라이언트가 최초 호출시에 생성을하며, 그 이후 생성이 된 인스턴스를 전역에서 공유한다.

보통 생성자를 Private로 만들고, 클래스 안에서 이 생성자를 호출하여 하나의 인스턴스만 생성하는 방법을 사용한다.

 

생성자를 Private로 하는 이유는 외부에서 이 객체를 생성하지 못하게 하기 위함이다.

 

namespace Library.DesignPattern.Singletone
{
    public class SingletonBase
    {
        public static readonly SingletonBase Instance = new SingletonBase();
        private string Test = "";
        private SingletonBase()
        {
            Test = "Test";
        }

        public string Some()
        {
            return Test;    
        }
    }
}

가장 기본적인 싱글톤 패턴의 구현 형식이다.

SingletonBase클래스는 Static 변수로 자기 자신을 인스턴로 하나 가지고 있고 이 인스턴스는 Private의 자기 생성자를 이용해 인스턴스를 만든다. 생성자에는 Test String변수를 초기화하고 있다.

이걸 사용하는 클라이언트 로직을 확인해 보겠다.

string test = SingletonBase.Instance.Some();
Console.WriteLine(test);

클라이언트는 클래스 인스턴스를 따로 만들필요없이 위의 코드 방법과 같이 static으로 선언된 인스턴스에 접근하여 초기화된 데이터를 접근할 수 있다. 

 

이런 싱글톤 디자인 패턴은 보통 하나의 프로그램에서 하나의 데이터만 만들어야 할 경우 사용된다.

예를 들어 프로그램의 환경설정(Config)나 자주 접근을 해야 하는 데이터(자주 쓸 데이터를 필요할 경우 계속 만 들 경 우 자원이 계속 만들어져 리소스 낭비가 심하다)

 

하지만 위의 싱글톤패턴에 함정이 있다.

만약 싱글톤패턴에서 생성되어야 할 데이터가 20초가 걸린다고 가정한다면

저 싱글톤 인스턴스가 만들어지는 순간 20초가 프리징 되어 화면이 멈추는 현상이 생길 것이다.

 

위와 같은 문제가 빈번하여 닷넷에서는 이를 쉽게 해결 할 수 있는 Lazy객체를 제공해준다.

Lazy는 뜻대로 늦은 초기화로 인스턴스가 생성되는동안 해당 스레드를 잠그지 않고 비동기 비슷하게 객체를 생성할 수 있다. 그럼 Lazy로 싱글톤 패턴을 사용하는 방법을 알아보자.

 

 

public class SingletonLazy
    {
        private static readonly Lazy<SingletonLazy> instance = new Lazy<SingletonLazy>(() => new SingletonLazy());
        public static SingletonLazy Instance
        {
            get => instance.Value;
        }

        private string Test = "";


        private SingletonLazy()
        {
            Test = "test lazy";
        }

        public string Some()
        {
            return Test;
        }
    }
string test = SingletonLazy.Instance.Some();
Console.WriteLine(test);

lazy객체를 통해서 인스턴스를 초기화하게 되면 해당 쓰레드가 잠기지 않고 프로그램이 잠기지 않게 됩니다.

보통을 닷넷에서 소개 드린 두 가지 방법으로 싱글톤을 사용하게 됩니다.

반응형

댓글