Static vs Singleton

기훈·2025년 6월 23일

Java

목록 보기
6/6

개발을 진행하다 보면 프로그램 전반에서 공유되는 전역 객체를 만들어야 할 때가 있다.
이때 static으로 할지, Singleton으로 할지 고민하는 경우가 많지만
실제로는 명확한 기준 없이 느낌에 따라 결정하는 경우가 많다.

개인적으로 프로그래밍에서 근거 있는 선택은 매우 중요하다고 생각한다..
그래서 이번 기회에 staticSingleton의 차이를 정리하고
언제 어떤 상황에서 선택해야 하는지에 대해 비유와 예제를 통해 명확히 해보려 한다.


기본 개념 비교

항목staticSingleton
정의클래스 로딩 시 메모리에 올라가는 정적 자원애플리케이션에서 단 하나의 인스턴스를 보장하는 전역 객체
메모리 관리JVM 종료 전까지 존재 (GC 대상 아님)GC 대상이 될 수 있음
상태 관리상태를 가지면 위험 (모든 스레드가 공유)상태를 가지되, 스레드별 제어 가능 (예: ThreadLocal)
스레드 안전성직접 제어 어려움동기화 또는 ThreadLocal로 제어 가능
제어 가능성불변에 가깝고 초기화 이후 제어 어려움라이프사이클, 초기화, 해제 등 명시적으로 제어 가능
주요 사용 예상수, 유틸성 로직 (Math, Collections, 포맷터 등)DB 커넥션 풀, 세션 관리자, 설정값 캐시 등 상태가 있는 전역 객체

비유: 자동차 공장에 빗대어 이해하기

개념자동차 공장 비유
static공장 한가운데 있는 공용 공구상자
모든 작업자가 공유하며, 상태가 없거나 공유해도 괜찮은 계산기·자 모음 등
Singleton공장 전체를 통제하는 중앙 통제기(제어 장치)
상태를 가지며, 각 작업자(스레드)가 안전하게 접근해야 하는 구성요소 (예: 세션 관리자, 설정 캐시 등)

핵심 요약

  • static무상태인 전역 도구
  • Singleton상태를 가지되, 제어 가능한 전역 객체

✔️ 무상태이면 static,
✔️ 상태와 제어가 필요하면 Singleton


실제 예시: UserSessionManager (싱글톤 + ThreadLocal)

public class UserSessionManager {
    private static final UserSessionManager INSTANCE = new UserSessionManager();

    // ThreadLocal을 이용한 사용자 세션 분리
    private final ThreadLocal<String> currentUser = new ThreadLocal<>();

    private UserSessionManager() {}

    public static UserSessionManager getInstance() {
        return INSTANCE;
    }

    public void login(String username) {
        currentUser.set(username);
    }

    public String getCurrentUser() {
        return currentUser.get();
    }

    public void logout() {
        currentUser.remove();
    }
}

왜 Singleton이 적절한가?

UserSessionManager가 Singleton인 이유

  • 전역에서 한 번만 생성되어야 하며,
  • 내부에 상태(currentUser)를 가지고 있음
  • 단, 스레드마다 상태를 안전하게 분리해야 하므로 ThreadLocal을 사용함
  • Singleton으로 구현하면:
    • 전역 접근이 가능하면서도
    • 스레드마다 고립된 상태 관리가 가능함

static으로 하면 왜 안 되는가?

  • static 필드에 상태를 저장하면 모든 스레드가 같은 값을 공유하게 됨
  • 동시 요청 시 사용자 세션 정보가 덮어쓰기되거나 섞일 위험
  • 또한 static초기화, 재설정, 수명 관리가 불가능해 유연성이 낮음

요약 비교

항목staticSingleton
객체 필요 여부❌ 인스턴스 없이 바로 사용 가능✅ 단 하나의 인스턴스를 통해 사용
상태 보유❌ 지양됨 (전역 공유 위험)✅ 가능 (ThreadLocal 등으로 안전하게 분리)
대표 사용 사례Math, Utils, 상수 클래스 등설정 캐시, 세션 관리자, DB 커넥션 풀 등

마무리

staticSingleton은 모두 전역 자원처럼 보이지만,
상태 관리와 라이프사이클 제어 가능성에서 큰 차이가 있다.

정리 기준은 단순하다다:

  • 계산만 하는 유틸 도구 → static
  • 상태를 가지며 제어가 필요한 전역 객체 → Singleton

0개의 댓글