"오늘의 문제를, 내일의 기록으로 남깁니다."

막연한 이론보다, 구체적인 코드가 필요할 때. 직접 겪고 해결한 문제들을 기록합니다. 실무에서 부딪히는 진짜 이슈와, 내가 이해한 방식 그대로 정리한 가이드입니다.

웹개발/Java

자바 static 키워드 제대로 알고 써보자 (사용법, 주의사항 총정리)

자바를잡아 2025. 7. 9. 21:00
반응형

자바 static 키워드, 제대로 이해하고 써야 하는 이유

얼마 전 회사에서 기존 시스템 유지보수를 하다 난감한 상황이 생겼다. 서버가 재시작되자마자 유저 수 카운트가 매번 0으로 초기화되어 버리는 문제였다. 곧바로 코드 점검을 하면서 static 키워드를 잘못 사용한 것을 발견했다. 이 일을 계기로 static의 정확한 사용법과 주의사항을 다시 한번 짚어봐야겠다고 생각했다.

이번 포스팅에서는 자바의 static 키워드를 언제, 어떻게 써야 하는지 정확히 알려주고, 실무에서 자주 겪게 되는 실수 사례와 올바른 해결법을 함께 공유한다.

static 키워드의 의미와 필요성

자바에서 static은 클래스 멤버(변수, 메서드)에 붙여서 사용하는 키워드다. static 멤버는 인스턴스가 아니라 클래스 자체에 속하기 때문에, 인스턴스 생성 없이 직접 접근할 수 있는 특징을 가진다.

  • 클래스 변수(static 변수): 모든 인스턴스가 공유하는 변수
  • 클래스 메서드(static 메서드): 인스턴스 생성 없이 호출 가능한 메서드
  • 정적 초기화 블록(static 블록): 클래스가 로드될 때 한 번만 실행되는 코드 블록

static 키워드, 언제 써야 할까?

1. 모든 인스턴스가 공유해야 하는 데이터를 다룰 때

예를 들어, 생성된 객체의 개수를 카운트하는 상황이라면 static 변수를 사용해야 한다.

public class User {
    private static int userCount = 0;

    public User() {
        userCount++;
    }

    public static int getUserCount() {
        return userCount;
    }
}

// 사용 예시
public class App {
    public static void main(String[] args) {
        User user1 = new User();
        User user2 = new User();

        System.out.println(User.getUserCount()); // 출력: 2
    }
}

2. 인스턴스를 생성하지 않고 바로 호출해야 할 메서드

자주 사용하는 유틸리티 메서드도 static으로 만드는 것이 좋다.

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

// 사용 예시
public class App {
    public static void main(String[] args) {
        int sum = MathUtil.add(10, 20);
        System.out.println(sum); // 출력: 30
    }
}

3. 클래스가 로드될 때 초기화 작업이 필요할 때

정적 초기화 블록을 사용해 클래스가 로드될 때 필요한 초기화 작업을 수행할 수 있다.

public class Config {
    public static String appName;

    static {
        // 클래스가 로드될 때 한 번만 실행됨
        appName = "MyApp";
    }
}

// 사용 예시
public class App {
    public static void main(String[] args) {
        System.out.println(Config.appName); // 출력: MyApp
    }
}

static 키워드 잘못 쓰면 큰일 난다

1. 무분별한 static 사용으로 메모리 누수 발생

static 변수는 클래스가 로드된 후 프로그램 종료 시까지 유지된다. 무분별하게 많은 static 변수를 사용하면 메모리 낭비가 심각해질 수 있다.

2. 멀티스레드 환경에서 동기화 문제 발생 가능

static 변수는 모든 인스턴스가 공유하기 때문에 여러 스레드에서 동시에 접근할 경우 값이 꼬이거나 동기화 문제가 발생할 수 있다.

이럴 땐 synchronized 키워드로 동기화를 해주는 것이 필요하다.

public class Counter {
    private static int count = 0;

    public synchronized static void increment() {
        count++;
    }

    public static int getCount() {
        return count;
    }
}

static 메서드에서 주의할 점

1. static 메서드 내에서 인스턴스 멤버 접근 불가

static 메서드는 인스턴스가 아닌 클래스 단위로 호출되기 때문에, 인스턴스 변수나 메서드에 접근할 수 없다.

public class Example {
    private int instanceVariable = 5;

    public static void staticMethod() {
        // System.out.println(instanceVariable); // 컴파일 오류
    }
}

2. 상속 시 오버라이딩 불가능

static 메서드는 클래스 메서드로 간주되기 때문에 오버라이딩이 아닌 '숨김(hiding)'만 가능하다. 부모 클래스와 자식 클래스에서 같은 이름의 static 메서드를 정의하면, 호출할 때 참조 타입에 따라 결정된다.

class Parent {
    public static void print() {
        System.out.println("부모 클래스");
    }
}

class Child extends Parent {
    public static void print() {
        System.out.println("자식 클래스");
    }
}

public class App {
    public static void main(String[] args) {
        Parent.print(); // 출력: 부모 클래스
        Child.print();  // 출력: 자식 클래스

        Parent p = new Child();
        p.print(); // 출력: 부모 클래스 (메서드 숨김)
    }
}

결론: static 사용법 제대로 알고 쓰자

static 키워드는 적절히 사용하면 매우 편리하지만, 오용할 경우 프로그램의 성능이나 유지보수성에 큰 영향을 줄 수 있다. 특히 static 멤버가 메모리에 영구적으로 남아있는 특성을 이해하고, 필요한 경우에만 사용하도록 해야 한다.

코드를 작성할 때 static 멤버의 목적과 용도를 정확히 파악한 후 사용하여 불필요한 문제를 방지하는 것이 중요하다. 이번 포스팅을 통해 static 키워드 사용에 대한 감을 확실히 잡기를 바란다.

반응형