728x90
반응형
이전 글에서 이어지는 내용
[Error] 키오스크 트러블 슈팅 1
enum 상수과 switch문으로 관리하던 상태에서 상태 패턴 적용 해보는 것도 괜찮을 것 같다고 하셔서 검색 후 내 코드에 적용해 보았다. 기존에 키오스크 실질적인 기능을 담당하는 start() 메소드가
devz0.tistory.com
키오스크 프로그램을 작성하면서 상태패턴을 도입했다.
Kiosk 클래스가 State를 관리하고, 각 상태(START, MAIN_MENU, SUB_MENU, CART, ORDER)는 사용자의 입력에 따라 다음 상태로 전이된다.
초기 설계에서는 Kiosk 내부에서 상태 전이(currentState = State.MAIN_MENU)를 직접 수행했지만,
점차 책임 분리의 중요성을 알게되며 로직을 수정하다 State와 Kiosk 간의 책임이 뒤섞이는 문제가 발생했다.
문제
상태 전이의 책임이 Kiosk와 State 양쪽에 섞여 있음
- 비교적 간단한 상태 전환만 일어나는 일부 상태(START, MAIN_MENU)는 State 내부에서 다음 상태를 결정했지만,
다른 상태(SUB_MENU,CART, ORDER)는 Kiosk의 내부 메서드에서 currentState를 직접 바꿨다. - Kiosk가 State를 제어하고 State도 Kiosk를 제어하는 양방향 의존 구조가 됨
요약
- 로직의 흐름을 추적하기 어려움
- 유지보수를 하기 위해선 두 클래스 모두를 손대야 함
상태 관리의 응집도가 낮아지고, 결합도가 높아짐
원인
- 상태 전이 책임이 명확하지 않음
- handleOptional() 등 추가 메서드 내부에서 상태를 바꾸는 로직이 섞여 있었다.
- 일부 State가 다음 상태를 반환하지 않고, Kiosk 내부에서 currentState를 변경.
- 상태와 로직이 분리되지 않음
- Kiosk가 상태 전이 + 동작 수행 두 역할을 동시에 수행.
- 패턴의 의도 오해
- 상태패턴의 핵심은 상태가 다음 상태를 스스로 결정한다인데,
초기 설계는 Kiosk가 상태를 바꿔주는 구조
- 상태패턴의 핵심은 상태가 다음 상태를 스스로 결정한다인데,
해결 방안
로직이 조금 복잡해지더라도 책임 분리를 온전하게 진행 하는 편이 낫다고 판단해 설계를 재정의 했다.
- 모든 State가 handle(Kiosk kiosk) 메서드에서 다음 상태를 직접 반환하도록 통일
Kiosk.java
while (currentState != State.EXIT) {
currentState = currentState.handle(this);
}
- Kiosk의 역할 - 입출력 처리, 필드 관리 :
- 메뉴 리스트, 장바구니, 사용자 입력 등 공유 필드 관리
- 각 State가 사용할 유틸 메서드,UI 출력 메소드 제공
- State의 역할 - 상태 전이 제어 :
- 입력값 해석 및 다음 상태 결정
결과
- UI 출력 로직이 모두 한곳(Kiosk)에 모임 → 유지 보수 용이
- State는 오로지 “상태 전이”만 담당 → 로직 명확해짐
배운 것
- 상태패턴의 핵심은 행동의 위임이 아니라 상태 전이의 책임 분리다.
- 상태 전이 책임이 Kiosk에 있으면 흐름이 꼬인다. 상태패턴은 State가 스스로 다음 State를 반환하는 구조로 연결
- “어디서 상태가 바뀌는가?”를 기준으로 역할을 나누면 설계가 자연스럽게 정리된다.
- 이 구조는 이전보다 Open-Closed Principle(OCP)을 충실히 따르며, 유지보수성과 확장성이 대폭 향상되었다.
더 생각해 볼 것
- 현재 State는 상태 전이 에만 관여하고 있다. 유지보수를 하더라도 이전처럼 kiosk와 enum 클래스 두곳을 봐야함. State가 사용자 인터페이스까지 출력을 하는게 좋을까?
- 장점 : enum 상태만 보면 무슨 일이 일어나는지 알 수 있음, 응집도 올라감
- 단점: 다른 동작로직과 상태전이 로직이 섞임, enum 클래스가 무거워짐
728x90
반응형
'Dev. > Error.' 카테고리의 다른 글
| [Error] 자바에서 객체의 동등성과 동일성 문제 (0) | 2025.10.29 |
|---|---|
| [Error] 키오스크 트러블 슈팅 3 - 장바구니 구조 설계 (0) | 2025.10.28 |
| [Error] 키오스크 트러블 슈팅 1 - 상태 패턴 (0) | 2025.10.25 |
| [Error] 계산기 만들기 트러블 슈팅 (0) | 2025.10.17 |
| [Error] incompatible types: Object[] cannot be converted to String[] (0) | 2025.10.13 |