Waylog Blog

싱글톤(Singleton) 패턴: 유용함과 안티패턴 사이

Design Pattern

디자인 패턴 중 가장 유명하면서, 동시에 가장 욕을 많이 먹는 패턴입니다. 싱글톤 패턴은 클래스의 인스턴스를 오직 하나만 생성하고, 어디서든 이 인스턴스에 접근할 수 있도록 하는 패턴입니다.

1. 언제 쓸까?

  • 설정 관리 (Configuration): 앱 전체에서 공유해야 하는 환경 설정 객체.
  • Logger: 로그를 파일 하나에 모아서 써야 할 때.
  • DB Connection Pool: 커넥션 생성 비용이 비싸므로 하나 만들어두고 돌려쓸 때.

2. Java 코드 예시

public class Singleton {
    private static Singleton instance;
    
    private Singleton() {} // 생성자를 private으로 막음

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

3. 왜 안티 패턴이라고 불릴까?

3.1 테스트의 어려움

단위 테스트는 서로 독립적이어야 하는데, 싱글톤은 전역 상태를 공유하므로 A 테스트에서 상태를 바꾸면 B 테스트가 실패할 수 있습니다. Mocking 하기도 까다롭습니다.

3.2 의존성 숨기기

생성자나 인자로 주입받는 게 아니라 내부에서 getInstance()를 몰래 호출하므로, 클래스 선언부만 봐서는 얘가 누구랑 의존성(Coupling)을 맺고 있는지 알 수가 없습니다.

3.3 동시성(Concurrency) 문제

멀티 스레드 환경에서 동시에 if (instance == null)을 통과하면 인스턴스가 두 개 생길 수 있습니다. 이를 막으려면 synchronized 처리를 해야 하는데 성능이 떨어집니다.

4. 대안

Spring 같은 프레임워크를 쓴다면 의존성 주입(DI) 컨테이너가 빈(Bean)들을 기본적으로 싱글톤으로 관리해 줍니다. 개발자가 직접 싱글톤을 구현할 필요 없이, 프레임워크에게 생명주기 관리를 맡기는 것이 현대적인 모범 사례입니다.