static

2026. 2. 5. 20:04·Java

 

자바에서 static은 한마디로 “객체(인스턴스)가 아니라 클래스에 소속된다” 는 뜻이다.
그래서 static이 붙은 멤버는 new로 만든 객체마다 따로 생기는 게 아니라, 클래스 전체가 공유하는 단 하나가 된다.

서블릿, 톰캣, 멀티스레드 환경에서 static이 자주 언급되는 이유도 바로 이 “공유” 특성 때문이다.

 

1) static이 붙으면 뭐가 달라지나?

인스턴스 멤버(기본)

class User {
    int age;
}
  • new User()를 할 때마다 age는 각 객체마다 따로 존재한다.
  • 즉, 객체가 10개면 age도 10개다.

static 멤버

class User {
    static int count;
}
  • User 클래스에 count는 딱 1개만 존재한다.
  • new User()를 100번 해도 count는 여전히 1개다.
  • 모든 객체가 같은 User.count를 공유한다.

 

 

static 변수는 언제 만들어지나? (초기화 시점)

static은 클래스가 JVM에 로딩될 때 만들어진다.

즉,

  • 프로그램 실행 중 User 클래스를 처음 사용하는 순간(정확히는 클래스 로딩/초기화 단계)
  • static 필드가 메모리에 잡히고 초기화된다.

예:

class A {
    static int x = 10;
}

A를 처음 참조하는 순간 x가 준비된다.

 

 

메모리 관점으로 보는 static (스택/힙과 비교)

자바 실행 시 메모리를 크게 나누면 이런 식으로 이해하면 된다.

  • 스택(Stack): 메서드 호출 시 생기는 지역 변수(스택 프레임). 호출 끝나면 사라짐.
  • 힙(Heap): new로 만든 객체가 저장됨. GC 대상.
  • 클래스 영역(메서드 영역/Metaspace): 클래스 메타정보와 static 관련 데이터가 관리됨(개념적으로).

핵심은 이거다.

  • static은 객체(new)와 무관하게 클래스 쪽에 붙는다.
  • 그래서 “누가 new를 하든” 상관없이 항상 같은 하나를 바라본다.

 

 

static 접근 방식: 왜 클래스명.변수로 쓰는가?

static은 클래스 소속이므로 아래 방식이 정석이다.

User.count++;
System.out.println(User.count);

물론 객체로도 접근은 “가능”하지만(경고 느낌)

User u = new User();
u.count++; // 동작은 하지만 본질은 클래스 공유값이라 혼동 유발

실제로는 u.count도 내부적으로 User.count로 해석된다.

 

 

static 메서드란?

static 메서드도 동일하게 클래스 소속 메서드다.

class MathUtil {
    static int add(int a, int b) { return a + b; }
}

호출:

MathUtil.add(1, 2);

static 메서드의 중요한 제약

static 메서드 안에서는 인스턴스 멤버에 바로 접근할 수 없다.

class A {
    int n = 10;
    static void f() {
        // System.out.println(n); // 불가능
    }
}

이유는 명확하다.

  • static은 “특정 객체”가 없을 수도 있는 상태에서 호출된다.
  • 그런데 n은 “특정 객체”에 속한다.
  • 어떤 객체의 n인지 결정할 수 없으니 막는 것이다.

 

 

static의 대표적인 사용 패턴 4가지

(1) 상수(constants)

public class HttpStatus {
    public static final int OK = 200;
}
  • 공통으로 쓰는 값, 변경 불가, 어디서든 접근 가능

(2) 유틸리티 클래스(Utility)

public class StringUtils {
    public static boolean isBlank(String s) { ... }
}
  • 상태 없이 기능만 제공

(3) 공유 캐시 / 레지스트리

public class RequestMapping {
    private static final Map<String, Controller> map = new HashMap<>();
}
  • 서버 시작 시 한 번 세팅하고 계속 재사용하는 구조에서 자주 사용

(4) 싱글톤(singleton) 형태

 
public class AppConfig {
    private static final AppConfig INSTANCE = new AppConfig();
    public static AppConfig getInstance() { return INSTANCE; }
}
  • 애플리케이션 전역에서 1개만 쓰고 싶을 때

 

 

가장 중요한 주의점: static은 “전역 공유 상태”다

static이 강력한 이유는 “공유”지만, 위험한 이유도 “공유”다.

멀티스레드에서 문제 생기는 전형적인 상황

  • 요청이 동시에 100개 들어온다.
  • 모든 스레드가 같은 static 값을 동시에 읽고/쓴다.
  • 동기화 없이 업데이트하면 경쟁 조건(race condition)이 발생한다.

예:

static int count = 0;

count++; // 이 한 줄도 스레드 안전하지 않을 수 있음

그래서 서블릿/톰캣 같은 환경에서는 특히 조심해야 한다.

  • 서블릿 인스턴스도 보통 1개 공유
  • static도 1개 공유
    → 둘 다 “공유 상태”가 되기 쉬움

 

 

“서블릿 맥락”에서 static을 어떻게 봐야 하나?

서블릿 컨테이너는 멀티스레드로 동작하고, 서블릿 인스턴스를 보통 하나만 만들어 공유한다는 특성이 있다.
여기서 static까지 쓰면 공유 범위가 더 커진다.

  • 서블릿 인스턴스 필드: “그 서블릿 인스턴스 1개”에 공유됨
  • static 필드: “클래스 자체”에 공유됨 (서블릿 인스턴스가 몇 개든 상관없이 공유)

결론:
요청마다 달라지는 값(사용자 정보, 요청 데이터, 임시 계산값)을 static에 저장하면 거의 무조건 사고 난다.

 

 

안전하게 쓰는 기준

static을 써도 되는 대표 케이스:

  • public static final 상수
  • 상태 없는 유틸 메서드
  • 불변(immutable) 객체의 공유 참조
  • 읽기 전용 캐시(초기화 후 변경 없음)
  • 동시성 제어가 확실한 공유 구조(ConcurrentHashMap, Atomic*, synchronized 등)

조심해야 하는 케이스:

  • 요청마다 변하는 값을 static에 저장
  • 누적 카운터, 리스트에 add 같은 변경 작업을 동기화 없이 수행
  • 테스트에서 전역 상태 때문에 케이스 간 간섭 발생

 

 

정리

static은 “클래스에 붙는 공유 멤버”라는 단순한 문법이지만, 실제로는 다음을 의미한다.

  • 인스턴스와 무관하게 1개만 존재한다
  • 어디서든 접근 가능한 전역 공유 상태가 된다
  • 멀티스레드 환경에서는 동시성 이슈의 출발점이 된다

'Java' 카테고리의 다른 글

왜 new Integer()를 사용하면 안 될까?  (0) 2026.02.13
enum: 사용이유와 예시  (0) 2026.02.04
쓰레드란?  (0) 2026.01.29
'Java' 카테고리의 다른 글
  • 왜 new Integer()를 사용하면 안 될까?
  • enum: 사용이유와 예시
  • 쓰레드란?
sqaxe1
sqaxe1
woojoo-devlog 님의 블로그 입니다.
  • sqaxe1
    Woojoo's Devlog
    sqaxe1
  • 전체
    오늘
    어제
    • 분류 전체보기 (148)
      • Backend (9)
        • Servlet (7)
        • Spring (2)
      • Frontend (1)
      • CS (0)
      • Book (33)
        • 자바 웹 프로그래밍 Next Step (30)
        • 테스트 주도 개발: 고품질 쾌속개발을 위한 TDD.. (1)
        • 성공과 실패를 결정하는 1%의 네트워크 원리 (2)
      • Engineering (0)
        • Testing (0)
      • Infra (6)
        • AWS (6)
      • Java (4)
      • Network (1)
      • 김영한 (28)
        • 자바 입문 (8)
        • 실전 자바 - 기본편 (6)
        • 실전 자바 - 중급편 (10)
        • 실전 자바 - 고급편 (4)
      • Web (39)
        • Web Basics (39)
      • Project (24)
        • NeoSquare (0)
        • Memo Evolution (24)
      • 정보처리기사 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발서적
    java
    aws
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
sqaxe1
static
상단으로

티스토리툴바