꼬꼬마 블로그

꼬꼬마의 기술 블로그

안녕하세요

팀의 소스코드에서 싱글톤을 사용하는 것을 본 이후로 싱글톤 패턴에 대해서 공부해봐야지라는 생각을 했습니다. 하지만 막상 어떨 때 어떻게 써야 할지 몰라서 공부를 못하고 있다가 이번에 싱글톤 패턴을 쓰기 좋은 기회가 온 것 같아 공부해 사용해보려고 합니다.

그래서 이번 글에서는 객체지향의 디자인 패턴중싱글톤 패턴에 대해서 알아보도록 하겠습니다.

싱글톤 패턴

싱글톤 패턴은 인스턴스가 프로그램에서 하나만 생성되고, 어디서든 인스턴스에 접근할 수 있도록 하는 패턴입니다.

아래의 코드를 통해 이해해보도록 하겠습니다.

public class Singleton {
    private static Singleton instance;

    private Singleton() { }

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

        return Singleton.instance;
    }
}

일단 싱글톤의 특징은 private 생성자를 가진다는 것과 인스턴스, 인스턴스에 접근하는 메서드(getInstance()) 가 static 으로 선언되었다는 점입니다.

getInstance() 메소드가 실행되면 인스턴스가 존재하는지 확인한 후 없다면 생성자를 통해 할당하고 인스턴스를 반환합니다.

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

    private Singleton() { }

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

        return Singleton.instance;
    }

    public void printCount() {
        System.out.println(count);
    }

    public void increaseCount() {
        this.count += 1;
    }
}
public class Main {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.increaseCount();
        singleton.printCount();

        Singleton singleton2 = Singleton.getInstance();
        singleton2.printCount();
    }
}

위의 코드는 멤버 변수로 count를 가지고 count를 출력하고, 증가시키는 메소드를 가집니다.

메인에서 singleton 이라는 인스턴스를 가져온 후 증가시키고 출력합니다. singleton2 라는 인스턴스를 가져온 후 출력한다면 결과 값은 결국 각각 1, 1 이 찍히게 됩니다.

멀티 쓰레드

위의 코드는 멀티 쓰레드 환경에서 문제점이 발생합니다.

멀티 쓰레드일 경우 위의 인스턴스가 생성되었는지 확인하는 부분이 동시에 처리되어 여러 가지 인스턴스가 만들어질 수 도 있고, 멤버 변수의 값이 다른 프로세스에서 처리한다면 값이 일관되지 않을 수 있습니다. 이를 해결하기 위한 방법은 두 가지가 있습니다.

정적 변수에 바로 인스턴스를 만들어 초기화하는 방법

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

    private Singleton() { }

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

    public void printCount() {
        System.out.println(count);
    }

    public void increaseCount() {
        this.count += 1;
    }
}

위와 같은 방법으로 처음부터 인스턴스를 초기화합니다. 이 방법으로 인스턴스가 여러 가지 만들어지는 문제는 해결할 수 있습니다.

하지만 이 방법으로는 값을 일관시킬 수는 없습니다. 값을 일관시키기 위해서는 _synchronized _ 라는 키워드를 통해 값을 변형하는 메서드에 동기화하는 방법이 있습니다. 이에 관련된 내용은 아래 참고 문서를 확인하시면 더 자세하게 확인할 수 있습니다. 저는 DBCP와 비슷하게 구현할 목적으로 인스턴스의 상태를 변화시키지 않습니다. 그러므로 동기화하는 방법은 더 자세히 알아보도록 하겠습니다.

참고 문서


https://gmlwjd9405.github.io/2018/07/06/singleton-pattern.html

https://velog.io/@kyle/%EC%9E%90%EB%B0%94-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4-Singleton-Pattern

'개발 > 객체지향' 카테고리의 다른 글

어댑터 패턴 (Adapter Pattern)  (0) 2021.04.05
빌더 패턴 (Builder Pattern)  (0) 2021.03.29
객체지향 SOLID 원칙  (2) 2021.03.27