상태 패턴
더 많은 작업
상태 패턴(State Pattern)은 객체의 내부 상태마다 별도의 상태 클래스를 두고, 객체가 상태에 따라 달라지는 동작을 현재 상태 객체에 위임하게 하여 상태가 바뀌면 객체의 동작이 바뀌도록 하는 GoF 행위 디자인 패턴이다.
GoF 는 상태 패턴의 의도를 '객체의 내부 상태가 바뀔 때 행동을 바꿀 수 있게 하여, 객체가 마치 클래스를 바꾼 것처럼 보이게 하는 것'으로 적었다. 예로 든 TCPConnection 은 Established, Listening, Closed 상태에 따라 같은 Open 요청에도 다르게 반응하는데, 상태마다 TCPState 의 하위 클래스를 두고 TCPConnection 은 현재 상태 객체에 요청을 넘긴다.[1]
상태를 정수 상수나 플래그로 두면, 상태에 따라 동작이 달라지는 메서드마다 같은 모양의 if-else·switch 가 들어간다. 상태가 늘어날수록 모든 메서드의 조건문을 찾아 고쳐야 하고, 상태 전이 규칙을 바꾸는 것도 어렵다. 상태 패턴은 이런 조건문의 각 분기를 별도의 클래스로 옮긴다.[2]
| 참여자 | 역할 |
|---|---|
| Context | 클라이언트가 쓰는 객체. 현재 상태를 나타내는 ConcreteState 객체를 참조로 들고 있고, 상태에 따라 달라지는 요청을 그 객체에 위임한다 |
| State | 상태별 동작을 위한 공통 인터페이스(또는 추상 클래스) |
| ConcreteState | 상태 하나에 해당하는 동작을 구현한다. 필요하면 다음 상태로 전이시킨다 |
상태 전이는 Context 가 상태 객체를 다른 상태 객체로 바꿔 끼우는 것으로 일어난다. 전이 규칙을 Context 에 둘 수도 있고, 각 ConcreteState 가 자기 다음 상태를 정하게 할 수도 있다.[1]
경비 시스템이 주간·야간에 따라 다르게 동작한다고 하자. 바꾸기 전에는 메서드마다 시간대를 검사한다.
class 경비시스템 {
금고사용() { if (주간) 사용기록(); else if (야간) 비상통보(); }
비상벨() { 비상벨통보(); }
일반통화() { if (주간) 센터호출(); else if (야간) 자동응답기호출(); }
}
상태 패턴을 적용하면 시간대마다 같은 메서드 집합을 가진 상태 클래스가 생기고, 조건문이 사라진다.
interface 시간대상태 { 금고사용(); 비상벨(); 일반통화(); }
class 주간상태 implements 시간대상태 { 금고사용() { 사용기록(); } 비상벨() { 비상벨통보(); } 일반통화() { 센터호출(); } }
class 야간상태 implements 시간대상태 { 금고사용() { 비상통보(); } 비상벨() { 비상벨통보(); } 일반통화() { 자동응답기호출(); } }
class 경비시스템 { 시간대상태 state; 금고사용() { state.금고사용(); } ... 시간변경(h) { state = (주간이면 new 주간상태() : new 야간상태()); } }
새 시간대(예: 휴일)가 생기면 상태 클래스 하나를 더하면 되고, 기존 메서드의 조건문을 고치지 않는다.
- 상태별 동작이 한 클래스에 모여 지역화되고, 새 상태를 추가하기 쉽다
- 상태 전이가 '상태 객체 교체'라는 명시적인 동작이 되어 일관되지 않은 중간 상태가 생기지 않는다
- 클래스 수가 늘어난다. 상태가 두세 개뿐이고 바뀔 일이 없으면 조건문이 더 단순하다
- 인스턴스 변수가 없는 상태 객체는 여러 Context 가 공유할 수 있어 싱글톤으로 만들기도 한다[1]
| 패턴 | 목적 | 구별 포인트 |
|---|---|---|
| 상태 패턴 | 상태에 따라 객체의 동작을 바꾼다 | 상태 객체가 서로를 알고 스스로 전이를 일으킬 수 있다. 실행 중 상태가 계속 바뀐다 |
| 전략 패턴 | 알고리즘을 갈아 끼운다 | 구조는 같지만 전략끼리는 서로를 모르고, 보통 클라이언트가 한 번 골라 넣는다[2] |
| 어댑터 패턴 | 맞지 않는 인터페이스를 변환한다 | 기존 클래스를 감싸 다른 인터페이스로 보이게 할 뿐 동작 분기와 무관하다 |
| 빌더 패턴(GoF 디자인 패턴의 생성 패턴) | 복잡한 객체를 단계별로 조립한다 | 생성 과정의 패턴이다. 생성 후의 동작 변화와 무관하다 |
| 템플릿 메서드 패턴(GoF 디자인 패턴의 행위 패턴) | 상위 클래스가 알고리즘 골격을 정하고 하위 클래스가 단계를 채운다 | 상위 클래스에 공통 흐름을 담은 템플릿 메서드가 있어야 한다. 실행 중 객체를 바꿔 끼우지 않는다 |
- ↑ 1.0 1.1 1.2 Erich Gamma 외, 「State」, Design Patterns: Elements of Reusable Object-Oriented Software, 노스캐롤라이나 대학교 게시본, https://www.cs.unc.edu/~stotts/GOF/hires/pat5h.htm, 확인일: 2026-11-04.
- ↑ 2.0 2.1 「State」, Refactoring.Guru, https://refactoring.guru/design-patterns/state, 확인일: 2026-11-04.