일반적으로 데이터는 값(value)을 뜻하지만, 객체지향 프로그래밍에서는 “상태”로 설명합니다.
예를 들어 사용자의 포인트, 주문 상태(결제 전 / 후), 계정 잠금 여부 같은 값은 “현재 상태”를 의미합니다.
상태가 “그냥 저장되는 값”이 아니라, 행동(메서드)이 무엇을 할 수 있는지를 결정하고, 잘못 다루면 버그/보안/정합성 문제로 바로 이어진다는 것입니다.
“상태는 프로그램의 진실(Truth)이다.
진실이 흔들리면, 기능도 흔들린다.”
값(value)은 정적인 느낌이지만, “상태”는 시간 축이 들어갑니다.
예를 들어 주문은 CREATED → PAID → SHIPPED → DONE처럼 변하고, 이 흐름이 곧 비즈니스 로직입니다.
상태를 public setter로 마음대로 바꾸게 두면, “이 값은 항상 0 이상이어야 한다” 같은 규칙(불변 조건)이 쉽게 깨집니다.
상태를 캡슐화하고, 상태 변화는 의미 있는 메서드로만 하게 설계합니다.
// BAD: 외부에서 상태를 막 바꿀 수 있음 → 규칙 깨짐
class Account {
public int balance; public void setBalance(int v) {
balance = v;
}
}
// GOOD: 상태는 숨기고, 의미 있는 행동으로만 변경
class Account {
private int balance;
public Account(int initial) {
if (initial < 0) throw new IllegalArgumentException("balance must be >= 0");
this.balance = initial;
}
public void deposit(int amount) {
if (amount <= 0) throw new IllegalArgumentException("amount must be > 0");
this.balance += amount;
}
public void withdraw(int amount) {
if (amount <= 0) throw new IllegalArgumentException("amount must be > 0");
if (this.balance < amount) throw new IllegalStateException("insufficient");
this.balance -= amount;
}
public int balance() {
return balance;
}
// 읽기만 제공
}
💡 TIP / 참고사항
상태를 “감춘다”는 건 getter를 없애라는 뜻이 아니라, 상태 변경 경로를 통제하라는 의미입니다.
읽기는 가능해도, 변경은 규칙을 통과한 메서드로만 이루어지게 하는 게 안전합니다.
👍 GOOD (안정적인 상태 관리)
- 상태 변경은 “의미 있는 메서드”로만 허용
- 불변 조건(invariant)을 코드로 강제
- 동시성 환경에서는 락/트랜잭션/원자 연산으로 보호
- 상태 흐름은 enum/state machine으로 명확히 모델링
👎 BAD (깨지기 쉬운 상태)
- setter로 아무나 상태 변경 가능
- “일단 저장” 후 나중에 검증(이미 데이터가 오염됨)
- 동시 요청에서 재고/포인트가 음수로 떨어짐
- 상태 전이가 코드 곳곳에 흩어져 파악이 어려움
✅ 핵심 요약
- ✔️ 데이터(상태)는 객체/시스템의 현재 상황을 나타내는 값들의 집합이다.
- ✔️ OOP에서는 상태를 캡슐화하고, 변화는 의미 있는 메서드로만 통제하는 게 핵심이다.
- ✔️ 실무에서 상태는 동시성/정합성 문제와 직결되므로 불변 조건과 보호 전략이 필요하다.