숏컷 코드
입력
-> command 생성
-> queue / stack에 저장
-> 지금 실행하거나 나중에 재생문법과 예시
직접 메서드 호출은 "무슨 행동이 일어났는지"를 남기지 않는다
버튼 입력이 곧바로 player.MoveLeft()로 연결되면, 그 순간 행동은 실행되지만 기록은 남지 않습니다. 이 구조는 단순할 때는 충분합니다.
하지만 입력 기록, 리플레이, AI 계획, 실행 취소/다시 실행이 필요해지면 "행동 그 자체"를 값처럼 다뤄야 합니다. 커맨드 패턴은 메서드 호출을
오브젝트로 감싸서 그 행동을 저장, 지연, 취소하기 쉽게 만듭니다.
직접 호출
Input -> MoveLeft()
커맨드
Input -> MoveLeftCommand
-> 실행
-> history stack 저장queue와 stack은 command의 대표 활용 지점이다
실시간 액션 게임이라면 입력을 한 프레임 지연 없이 바로 실행하되, 같은 프레임에서 정렬된 순서로 처리하기 위해 queue를 둘 수 있습니다. 턴제, 전술, 에디터성 게임이라면 stack이나 history list가 더 중요합니다. 이전 command를 저장해 두면 replay, undo, deterministic debug 같은 흐름이 가능해집니다. 핵심은 "행동을 언제 실행할지"와 "실행 후 다시 다룰 필요가 있는지"를 구조로 분리하는 것입니다.
command object와 invoker를 나누면 입력 소스가 바뀌어도 구조가 유지된다
command object와 command invoker를 나누면 command는 행동 자체를 담고, invoker는 그것을 언제 실행할지 결정합니다. 이 분리가 있으면 키보드 입력, AI 계획, 네트워크 동기화가 모두 같은 command 형식을 사용할 수 있습니다. 입력 소스가 달라도 실행 경계는 유지되고, 행동 저장 방식도 통일됩니다.
장점은 기록 가능성이고, 단점은 객체 수와 되돌리기 비용이다
command 패턴의 장점은 입력 이력을 저장하고, 실행 타이밍을 제어하고, undo/replay 같은 후속 기능을 붙이기 쉽다는 점입니다. 반대로 행동마다 객체가 생기고, 역연산이나 이전 상태 복원이 필요할수록 비용이 커집니다. 단순 입력 처리에는 과할 수 있으므로, 책이 말하듯 "행동을 추적해야 하는가"가 먼저 판단 기준이 됩니다.
command가 맞는 경우와 그냥 함수 호출이 더 나은 경우는 다르다
버튼 클릭 하나가 설정 토글 하나만 바꾸는 단순 UI라면 command 객체가 과할 수 있습니다. 반대로 입력을 기록해야 하거나, 같은 행동을 사람/AI/네트워크 이벤트 모두에서 재사용해야 한다면 command가 유리합니다. 판단 기준은 행동을 "값처럼 저장하고 재생해야 하는가"입니다.
undo 가능한 command는 부작용 경계를 먼저 정해야 한다
실행 취소를 하려면 command가 실행 전 상태를 저장하거나, 되돌리는 역연산을 알아야 합니다. 이때 외부 시스템에 바로 퍼지는 부작용이 많으면 undo가 급격히 어려워집니다. 그래서 command는 보통 월드 상태를 바꾸는 경계와 함께 설계됩니다. 네트워크 송신, 연출 재생, UI 토스트까지 한 command에 다 섞으면 replay/undo 품질이 크게 떨어집니다.
command를 쓸 때 핵심
| 상황 | 적합한 선택 |
|---|---|
| 입력 기록, replay, undo가 필요할 때 | command 패턴 |
| 사람 입력과 AI 행동을 같은 형식으로 다루고 싶을 때 | command 객체로 통일 |
| 단순 버튼 토글처럼 저장 가치가 거의 없을 때 | 직접 함수 호출이 더 단순 |
| 실행 시점과 입력 시점을 분리해야 할 때 | queue 기반 command 실행 |
| 되돌리기 기능이 중요할 때 | history stack + undo 가능한 command 설계 |
| 외부 부작용이 큰 행동일 때 | 월드 변경과 부가 효과를 분리 |
| 입력 소스가 플레이어/AI/리플레이로 바뀔 수 있을 때 | invoker + command 구조로 통일 |
특이 케이스와 주의할 점
흔한 실패는 command에 실제 게임 로직, UI 반응, 네트워크 전송을 전부 한 번에 넣는 것입니다. 이렇게 되면 저장과 replay는 되더라도, 되돌리기와 테스트가 어려워집니다. command는 행동 경계를 명확히 하는 도구이지, 모든 부작용을 한 객체에 몰아넣는 컨테이너가 아닙니다. undo가 필요 없고 실행 기록도 안 남길 단순 입력까지 전부 command로 만들면 객체 수와 관리 비용만 늘어날 수 있습니다.
실패 예시
- AttackCommand 하나가
데미지 계산
애니메이션 실행
사운드 재생
네트워크 전송
토스트 표시까지 직접 처리
결과
- replay/undo 경계가 모호해짐
- 테스트도 command 단위로 과하게 무거워짐참고 링크
1 sources