목차
- static이란 무엇인가
- 정적 변수(Static Variable)
- 정적 메서드(Static Method)
- 실무 예제와 메모리 구조
- 자주 하는 실수와 해결법
1. static이란 무엇인가?
핵심 개념
static = 클래스 레벨에서 단 하나만 존재하는 공유 자원
Oracle 공식 문서에 따르면:
"Static members belong to the class instead of a specific instance"
java
public class CoffeeShop {
// 인스턴스 변수 - 각 점포별로 다름
private String branchName;
private int dailySales;
// static 변수 - 모든 점포가 공유
private static String brandName = "스타벅스";
private static int totalStores = 0;
private static double coffeePrice = 4500;
}
메모리 구조 시각화
JVM 메모리 구조
┌────────────────────────────────────┐
│ Method Area (Static) │
│ ┌─────────────────────────────┐ │
│ │ brandName: "스타벅스" │ │
│ │ totalStores: 3 │ │
│ │ coffeePrice: 4500 │ │
│ └─────────────────────────────┘ │
└────────────────────────────────────┘
↑ 공유
┌─────────────────────────────────────────┐
│ Heap Area │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 강남점 │ │ 판교점 │ │ 역삼점 │ │
│ │ sales:50 │ │ sales:30 │ │ sales:40 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────┘
2. 정적 변수 (Static Variable)
실무 예제: 쇼핑몰 배송 시스템
java
public class DeliveryService {
// 인스턴스 변수 - 주문별로 다름
private String orderId;
private String address;
private double weight;
// static 변수 - 전체 시스템 공유
private static double baseDeliveryFee = 3000; // 기본 배송료
private static int totalDeliveries = 0; // 총 배송 건수
private static boolean holidayMode = false; // 공휴일 여부
public DeliveryService(String orderId, String address, double weight) {
this.orderId = orderId;
this.address = address;
this.weight = weight;
totalDeliveries++;
}
// 배송료 계산 (인스턴스 메서드)
public double calculateFee() {
double fee = baseDeliveryFee;
if (weight > 5.0) {
fee += 1000; // 5kg 초과 시 추가 요금
}
if (holidayMode) {
fee += 2000; // 공휴일 추가 요금
}
return fee;
}
// 공휴일 설정 (static 메서드)
public static void setHolidayMode(boolean isHoliday) {
holidayMode = isHoliday;
if (isHoliday) {
System.out.println("공휴일 모드 활성화 - 추가 요금 적용");
}
}
}
3. 정적 메서드 (Static Method)
⚠️ 핵심 규칙
static 메서드는 인스턴스 변수/메서드에 접근 불가
java
public class Calculator {
private int memory = 0; // 인스턴스 변수
// ❌ 잘못된 static 메서드
public static void wrongMethod() {
memory = 10; // 컴파일 에러!
// Cannot make a static reference to non-static field
}
// ✅ 올바른 static 메서드
public static int add(int a, int b) {
return a + b; // 매개변수만 사용
}
}
왜 접근이 안 될까?
시나리오: Calculator.add(5, 3) 호출
┌──────────────────────────┐
│ Static Method 실행 │
│ │
│ "memory를 사용하라고?" │
│ ↓ │
│ 객체가 없는데? │
│ 누구의 memory? │
│ ↓ │
│ 에러 발생! │
└──────────────────────────┘
4. 실무 예제: API 요청 제한 시스템
java
public class ApiRateLimiter {
// 인스턴스 변수 - 사용자별
private String userId;
private int userRequestCount;
private long lastRequestTime;
// static 변수 - 시스템 전체
private static final int MAX_REQUESTS_PER_MINUTE = 60;
private static int totalRequestsToday = 0;
private static boolean maintenanceMode = false;
public ApiRateLimiter(String userId) {
this.userId = userId;
this.userRequestCount = 0;
this.lastRequestTime = System.currentTimeMillis();
}
// 인스턴스 메서드 - 개별 사용자 요청 처리
public boolean makeRequest() {
if (maintenanceMode) {
System.out.println("시스템 점검 중");
return false;
}
if (userRequestCount >= MAX_REQUESTS_PER_MINUTE) {
System.out.println(userId + ": 요청 한도 초과");
return false;
}
userRequestCount++;
totalRequestsToday++;
return true;
}
// static 메서드 - 시스템 관리
public static void enableMaintenance() {
maintenanceMode = true;
System.out.println("점검 모드 활성화");
}
public static void showStatistics() {
System.out.println("오늘 총 요청: " + totalRequestsToday);
System.out.println("분당 제한: " + MAX_REQUESTS_PER_MINUTE);
}
// 사용 예시
public static void main(String[] args) {
ApiRateLimiter user1 = new ApiRateLimiter("user001");
ApiRateLimiter user2 = new ApiRateLimiter("user002");
user1.makeRequest(); // 개별 요청
user2.makeRequest(); // 개별 요청
ApiRateLimiter.showStatistics(); // 전체 통계
ApiRateLimiter.enableMaintenance(); // 시스템 점검
}
}
메모리 상태 다이어그램
[Static 영역]
┌───────────────────────────────┐
│ MAX_REQUESTS: 60 │
│ totalRequestsToday: 2 │
│ maintenanceMode: false → true │
└───────────────────────────────┘
↑ ↑
┌────┴────┐ ┌────┴────┐
│ user1 │ │ user2 │
│ count:1 │ │ count:1 │
└─────────┘ └─────────┘
5. 자주 하는 실수와 해결법
❌ 실수 1: static 메서드에서 인스턴스 변수 접근
java
public class User {
private String name;
public static void printName() {
System.out.println(name); // 컴파일 에러!
}
}
해결:
java
public static void printName(User user) {
System.out.println(user.name); // 객체를 매개변수로 받기
}
❌ 실수 2: 개인정보를 static으로 선언
java
public class Account {
static String password; // 위험! 모든 계정이 같은 비밀번호
}
해결:
java
public class Account {
private String password; // 인스턴스 변수로 변경
private static String passwordPolicy = "8자 이상"; // 정책은 static
}
최종 정리표
특징 | static 변수 | static 메서드 | 인스턴스 변수 | 인스턴스 메서드 |
메모리 위치 | Method Area | Method Area | Heap | Heap |
생성 시점 | 클래스 로딩 | 클래스 로딩 | new 할 때 | new 할 때 |
개수 | 1개 | 1개 | 객체 수만큼 | 객체 수만큼 |
접근 방법 | 클래스명.변수 | 클래스명.메서드() | 객체.변수 | 객체.메서드() |
this 사용 | ❌ | ❌ | ⭕ | ⭕ |
암기 할 것
static = 공유 = 클래스 소속 = 객체 없어도 OK
인스턴스 = 개별 = 객체 소속 = 객체 필요
static 메서드 → static만 접근 가능
인스턴스 메서드 → 모든 것 접근 가능
참고 자료
'Java' 카테고리의 다른 글
Java | 메모리 구조 + static vs 인스턴스 종합 정리 (0) | 2025.10.04 |
---|---|
Java | Hiding (0) | 2025.10.04 |
Java | static vs 인스턴스 변수 차이점 (0) | 2025.10.04 |
Java | 업캐스팅과 다운캐스팅 (0) | 2025.10.02 |
Java | 자바 기본 개념 : 클래스, 객체, 상속 (0) | 2025.09.26 |