티스토리 뷰

구름/얄코 Java

Java 싱글톤 패턴

박완희버서커 2025. 11. 1. 09:31
반응형
Java 싱글톤 패턴(Singleton Pattern) 완전 이해 | Complete Guide to Java Singleton Pattern

Java 싱글톤 패턴(Singleton Pattern) 완전 이해

싱글톤 패턴의 개념

Java에서 싱글톤 패턴(Singleton Pattern)

“프로그램 전체에서 단 하나의 객체만 존재하도록 보장하는 설계 방식”입니다.

즉, 객체를 여러 번 만들지 않고 한 번만 생성해서 공유하는 구조입니다.

이 개념을 이해하려면 반대로 “싱글톤이 아닌 일반적인 객체 생성 방식”을 먼저 비교해보는 것이 좋습니다.


일반적인 객체 생성 방식과의 비교

일반적인 클래스는 new 키워드를 이용해 객체를 만들 수 있습니다.

예를 들어,

public class Counter {
    private int count = 0;

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

이 클래스를 여러 번 생성하면 각각의 객체가 독립적으로 존재합니다.

Counter c1 = new Counter();
Counter c2 = new Counter();

c1.increase(); // 1
c2.increase(); // 1

출력:

1
1

즉, c1과 c2는 서로 다른 객체이므로

각자의 count 변수를 따로 가지고 있습니다.

하지만 어떤 상황에서는 객체가 여러 개 만들어지는 것이 문제가 됩니다.

예를 들어,

  • 프로그램 전체에서 “로그 관리”를 하는 클래스
  • 데이터베이스 연결을 관리하는 클래스
  • 게임에서 “설정”이나 “점수판”처럼 하나만 있어야 하는 객체

이런 경우 객체가 여러 번 생성되면

설정이 서로 달라지거나, 데이터가 불일치하는 문제가 생깁니다.

이 문제를 해결하기 위해 등장한 것이 싱글톤 패턴입니다.


싱글톤 패턴의 구조

싱글톤 패턴의 핵심은

1. 객체를 단 한 번만 생성하고

2. 이후에는 항상 그 하나뿐인 객체를 반환하도록 만드는 것입니다.

이를 위해 Java에서는 다음과 같은 세 가지 요소를 반드시 포함합니다.

1. private 생성자

→ 외부에서 new로 객체를 만들지 못하게 막습니다.

2. private static 변수

→ 클래스 내부에 자기 자신의 인스턴스를 보관합니다.

3. public static 메서드

→ 외부에서 이 인스턴스를 가져갈 수 있게 합니다.

전체 구조를 코드로 보면 다음과 같습니다.

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

    private Singleton() { }

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

이 구조를 하나씩 분석하면 다음과 같습니다.

  • private Singleton() :
  • 생성자가 private이므로 외부에서 new Singleton()을 할 수 없습니다.

  • private static Singleton instance :
  • 자기 자신 타입의 객체를 클래스 내부에 미리 하나 만들어둡니다.

  • public static Singleton getInstance() :
  • 외부에서 이 객체를 가져갈 수 있도록 하는 공개된 메서드입니다.

이제 싱글톤 객체를 사용하는 코드를 보겠습니다.

Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();

두 객체를 비교해보면,

System.out.println(s1 == s2);

출력:

true

즉, 둘 다 같은 인스턴스를 가리키고 있습니다.

이제 프로그램 어디에서든 동일한 객체 하나만 공유하게 됩니다.


싱글톤 패턴의 동작 방식 확장 이해

싱글톤은 객체를 한 번만 만들고, 이후에는 이미 만들어진 객체를 재사용합니다.

이것은 마치 “건물의 관리자 사무실”과 같습니다.

건물에 여러 입주자가 있지만, 관리실은 하나만 존재하고

누구나 그곳에 문의해야 합니다.

즉,

  • getInstance()는 “관리실 문” 역할을 합니다.
  • 실제 관리실(instance)은 단 하나만 존재합니다.

게으른 초기화(Lazy Initialization) 방식

위의 예시는 프로그램이 시작되자마자

new Singleton()이 실행되어 인스턴스를 미리 만듭니다.

이 방법을 이른 초기화(Eager Initialization)라고 합니다.

하지만 어떤 경우에는

“정말 필요할 때까진 객체를 만들지 않고 싶다”는 요구가 있습니다.

그럴 때는 게으른 초기화(Lazy Initialization) 방식을 사용합니다.

public class Singleton {
    private static Singleton instance;

    private Singleton() { }

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

이 방식은 getInstance()가 처음 호출될 때만 객체를 생성하고,

그 이후에는 이미 만들어진 객체를 그대로 반환합니다.


싱글톤의 문제점과 해결법

싱글톤은 강력한 구조지만, 몇 가지 주의할 점이 있습니다.

1. 멀티스레드 환경에서의 동시성 문제

여러 스레드가 동시에 getInstance()를 호출하면

객체가 여러 번 생성될 수 있습니다.

이를 방지하려면 synchronized 키워드를 사용해 동기화해야 합니다.

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

다만 synchronized는 성능이 다소 느려질 수 있습니다.

그래서 더 효율적인 방법으로 Double-Checked Locking 기법을 사용하기도 합니다.

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;
    }
}

이렇게 하면 필요할 때만 잠금이 걸리므로 효율적입니다.

2. 테스트 어려움

싱글톤 객체는 전역적으로 하나만 존재하기 때문에

단위 테스트에서 독립적으로 환경을 구성하기 어렵습니다.

3. 객체 상태 공유에 따른 위험

여러 곳에서 하나의 객체를 공유하므로

내부 상태가 변경되면 프로그램 전체에 영향을 줄 수 있습니다.


싱글톤의 활용 예

싱글톤은 “전역에서 하나만 있어야 하는” 역할에 적합합니다.

사용 사례 설명
설정 관리자(Configuration Manager) 프로그램의 환경 설정을 중앙에서 관리
로깅 시스템(Logger) 여러 클래스가 동일한 로그 파일에 기록할 때
데이터베이스 연결 관리자(Connection Pool) 하나의 DB 연결 자원을 여러 곳에서 공유
캐시 관리자(Cache Manager) 자주 쓰는 데이터를 한 곳에 보관하고 재사용

예를 들어, 로그 관리기를 싱글톤으로 구현하면

프로그램의 어느 클래스에서도 같은 로그 객체를 통해 기록할 수 있습니다.

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

    private Logger() { }

    public static Logger getInstance() {
        return instance;
    }

    public void log(String msg) {
        System.out.println("[LOG] " + msg);
    }
}
Logger logger1 = Logger.getInstance();
Logger logger2 = Logger.getInstance();

logger1.log("프로그램 시작");
logger2.log("사용자 로그인");

출력:

[LOG] 프로그램 시작
[LOG] 사용자 로그인

두 객체가 같은 인스턴스를 공유하므로

로그가 동일한 경로를 통해 기록됩니다.


싱글톤 패턴의 장단점

구분 내용
장점 메모리 절약, 전역 접근 가능, 객체 일관성 유지
단점 테스트 어려움, 멀티스레드 문제 가능성, 높은 결합도 발생

결론

싱글톤 패턴은

“하나의 객체만 존재해야 하는 상황에서, 그 객체를 안전하게 관리하는 방법”입니다.

일반 클래스가 매번 새로운 객체를 만드는 반면,

싱글톤은 “단 하나의 인스턴스”를 만들어 프로그램 전체에서 공유합니다.

이 덕분에 메모리를 절약하고,

서로 다른 부분의 코드가 동일한 데이터를 참조할 수 있게 됩니다.

하지만 모든 상황에 싱글톤이 적합한 것은 아닙니다.

공유 상태가 많거나, 테스트가 중요한 구조에서는

오히려 유지보수를 어렵게 만들 수 있습니다.

따라서 싱글톤은 “필요할 때 신중하게 사용하는 설계 패턴”입니다.



반응형

'구름 > 얄코 Java' 카테고리의 다른 글

자바 익명 클래스(Anonymous Class)  (0) 2025.11.02
Java 람다식(Lambda Expression) 완벽 정리  (0) 2025.11.01
Java 내부 클래스(Inner Class)  (0) 2025.11.01
Java의 추상클래스  (0) 2025.11.01
Java의 인터페이스란?  (0) 2025.11.01
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/11   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함
반응형