자바 디자인 패턴 용어 사전
생성 패턴싱글톤 · 홀더 패턴 · 이중 검사 잠금

Singleton

인스턴스를 하나만 만들고 전역에서 접근하게 하는 패턴. 전역 상태라는 대가가 크다.

인스턴스를 하나만 만들고 전역에서 접근하게 하는 패턴.

구현 방법들

// ① 이른 초기화 — 가장 단순하고 스레드 안전
class Eager {
    private static final Eager INSTANCE = new Eager();
    private Eager() { }
    public static Eager getInstance() { return INSTANCE; }
}

// ② 홀더 패턴 — 지연 초기화 + 스레드 안전 (권장)
class Holder {
    private Holder() { }
    private static class H { static final Holder INSTANCE = new Holder(); }
    public static Holder getInstance() { return H.INSTANCE; }
}

// ③ enum — 직렬화·리플렉션 공격까지 막힌다
enum EnumSingleton { INSTANCE; public void work() { } }

②는 클래스 초기화의 스레드 안전성을 JVM이 보장한다는 성질을 이용한다 — 락도 volatile도 필요 없다.

이중 검사 잠금은 위험하다

private static volatile Singleton instance;   // volatile 이 빠지면 조용히 깨진다

static Singleton get() {
    if (instance == null) {
        synchronized (Singleton.class) {
            if (instance == null) instance = new Singleton();
        }
    }
    return instance;
}

객체 생성은 ⓐ할당 ⓑ생성자 실행 ⓒ참조 대입 세 단계다 ⓑ와 ⓒ가 재정렬되면 다른 스레드가 '반쯤 만들어진 객체' 를 받는다

  • volatile 이 그 재정렬을 막는다

굳이 이걸 쓸 이유가 없다 — 홀더 패턴이 더 짧고 안전하다

왜 안티패턴 취급을 받나

  • 전역 상태다 — 어디서 바뀌는지 추적이 어렵다
  • 테스트가 어렵다 — 교체할 수 없고 테스트 간 상태가 새어 나간다
  • 의존이 숨는다 — 생성자에 안 드러나므로 무엇을 쓰는지 알 수 없다
  • 멀티 클래스로더·멀티 JVM 에서는 하나가 아니다

대안

"인스턴스가 하나" 와 "전역에서 접근" 은 별개의 요구다

  • DI 컨테이너에 싱글톤 스코프로 등록하면
    • 인스턴스는 하나이면서 주입받아 쓰므로 테스트에서 교체할 수 있다

Spring 의 기본 빈 스코프가 정확히 이 방식이다

면접 함정

  • "싱글톤은 스레드 안전하다" → 인스턴스가 하나일 뿐, 그 안의 가변 상태는 여전히 위험하다.
  • "Spring 싱글톤 = GoF 싱글톤" → Spring은 컨테이너당 하나이고 평범한 클래스다.

안드로이드·서버에서의 현실

싱글톤이 필요해 보이는 것들

  • 설정 · 로거 · 커넥션 풀 · 캐시

이들의 공통점: '인스턴스가 하나' 가 목적이 아니라

- '비싼 자원을 공유' 하는 것이 목적이다
  • 그렇다면 DI 컨테이너의 싱글톤 스코프가 정확히 맞는 답이다
    • (인스턴스는 하나, 주입은 명시적, 테스트에서 교체 가능)
// 코틀린은 object 하나로 끝난다
object Config {
    val apiUrl = "https://api.example.com"
}
// 클래스 초기화의 스레드 안전성을 JVM 이 보장한다 — 홀더 패턴과 같은 원리

테스트가 어려운 이유를 구체적으로

테스트 A 가 Singleton 의 상태를 바꾼다 테스트 B 가 그 상태를 그대로 물려받는다

  • 실행 순서에 따라 결과가 달라진다 (flaky test)
  • 격리하려면 리플렉션으로 인스턴스를 초기화하는 해킹이 필요해진다

"테스트하기 어렵다" 는 대개 설계가 나쁘다는 신호다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 생성 패턴 — 객체를 만드는 일을 떼어낸다