JAVA [디자인패턴] - 싱글턴 패턴

gustjtmd·2025년 3월 17일

싱글턴 패턴(Singleton Pattern)은 클래스의 인스턴스를 하나만 생성하도록 제한하는 디자인 패턴이다. 특정 객체가 애플리케이션에서 하나만 존재해야 할 때 유용하다.

싱글턴 패턴의 중요성

  1. 메모리 절약
    인스턴스를 하나만 생성하므로 메모리를 절약할 수 있습니다.

  2. 데이터 일관성 유지
    하나의 인스턴스를 공유하므로 상태가 일관되게 유지됩니다.

  3. 접근 제어 및 동기화
    인스턴스 생성과 접근을 제어하여 스레드 안전성을 보장할 수 있습니다.

  4. 글로벌 상태 관리
    설정값, 로그, 설정 등을 전역에서 하나의 객체로 관리할 수 있습니다.


싱글턴 패턴을 적용하지 않은 경우

싱글턴 패턴을 적용하지 않으면 같은 객체를 여러 번 생성하게 됩니다. 이 경우 메모리 낭비와 상태 불일치가 발생할 수 있습니다.

싱글턴 패턴 미적용 코드로 확인해보기

public class Logger {
    public void log(String message) {
        System.out.println("Log: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        Logger logger1 = new Logger();
        Logger logger2 = new Logger();

        logger1.log("First log message");
        logger2.log("Second log message");

        System.out.println(logger1 == logger2); // false (서로 다른 객체)
    }
}

문제점

  • logger1logger2는 서로 다른 인스턴스이므로 상태가 일관되지 않습니다.
  • 인스턴스를 여러 개 생성하므로 메모리 낭비 발생 가능성이 높습니다.

싱글턴 패턴 적용한 경우

싱글턴 패턴에서는 인스턴스를 하나만 생성하고, 이를 전역에서 공유합니다.

싱글턴 패턴 적용 코드 예제

public class Logger {
    // 유일한 인스턴스를 저장할 정적 변수
    private static Logger instance;

    // 생성자를 private으로 선언해 외부에서 인스턴스화 방지
    private Logger() {}

    // 유일한 인스턴스를 반환하는 메서드
    public static Logger getInstance() {
        if (instance == null) {
            instance = new Logger();
        }
        return instance;
    }

    public void log(String message) {
        System.out.println("Log: " + message);
    }
}

public class Main {
    public static void main(String[] args) {
        Logger logger1 = Logger.getInstance();
        Logger logger2 = Logger.getInstance();

        logger1.log("First log message");
        logger2.log("Second log message");

        System.out.println(logger1 == logger2); // true (같은 객체)
    }
}

동작 방식

  1. Logger.getInstance() 호출 시 인스턴스가 없는 경우에만 생성
  2. 이미 인스턴스가 존재하면 기존 인스턴스를 반환
  3. 항상 하나의 인스턴스만 사용

스레드 안전한 싱글턴 패턴 적용

멀티스레드 환경에서 안전하게 작동하도록 synchronized 키워드를 추가하면 됩니다.

스레드 안전한 싱글턴 코드 예제

public class Logger {
    private static Logger instance;

    private Logger() {}

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

    public void log(String message) {
        System.out.println("Log: " + message);
    }
}

synchronized를 사용하면 멀티스레드 환경에서 경쟁 상태(race condition)를 방지할 수 있습니다. 하지만 성능이 저하될 수 있습니다.


정리

항목싱글턴 적용 전싱글턴 적용 후
인스턴스 수여러 개하나만 유지
상태 일관성불일치 가능일관성 유지
메모리 사용인스턴스마다 메모리 사용하나의 인스턴스만 메모리 사용
스레드 안전성경쟁 상태 발생 가능synchronized 또는 double-checked locking 적용 가능

결론:

  • 싱글턴 패턴은 상태 일관성, 메모리 절약, 성능 개선에 유용
  • 멀티스레드 환경에서는 synchronized 또는 Double-Checked Locking 적용
  • 너무 남용하면 코드 복잡도가 올라갈 수 있으므로 필요할 때만 사용
profile
반갑습니다

0개의 댓글