11키티즈 게임에서 XState를 선택한 이유

frontend , xstate

안영선's profile image

안영선

2025-04-16

Read more posts by this author

11키티즈 게임 화면

11키티즈 게임에서 XState를 선택한 이유

11키티즈 게임에서는 주요 비즈니스 로직 구현을 위하여 XState를 선택했다. 일반적인 프론트엔드 개발에서는 React의 useState, Redux, Zustand 등을 사용하여 상태를 관리하지만, 게임이라는 특수한 환경에서는 상태 전환의 명확성과 개발 생산성 및 품질 관리가 중요하다고 판단했기 때문이다. 이 글에서는 왜 웹 어플리케이션 게임 개발에서 XState가 효과적인지, 크게 두 가지 측면에서 그 이유를 설명하고자 한다.

1. 개발 생산성과 품질: 유한 상태 머신의 명확성

React는 본질적으로 ‘무한 상태 머신(Infinite State Machine)’이다. 즉, 상태가 조건이나 사용자 입력에 따라 자유롭게 변화하며, 무한한 상태 조합이 발생할 수 있다는 의미다. 이로 인해 복잡한 상태 전환 로직을 관리하기 어렵고, 상태 간의 의존성이 얽히기 쉬워져 버그 발생 가능성 또한 높아진다.

반면, XState는 ‘유한 상태 머신(Finite State Machine)’을 기반으로 한다. 유한 상태 머신은 정해진 상태와 명확한 전환 규칙을 선언적으로 정의하여 상태를 엄격히 제한한다. 각 상태에서 허용되는 전환을 명확히 명시하고, 각 상태의 동작을 완벽히 격리하여 관리할 수 있다. 이로써 코드 유지보수가 용이하고 예기치 못한 오류 가능성을 줄일 수 있다.

일반적으로 게임은 매우 많은 상태의 조합을 통해 게임 화면과 동작을 구현한다. 예를 들어 플레이어 캐릭터가 ‘대기’, ‘이동’, ‘공격’, ‘방어’ 등 명확한 상태를 가질 때, XState는 각 상태에서 허용 가능한 전환만을 명시적으로 정의하도록 한다. 이는 정의되지 않은 상태 전환을 원천적으로 방지하여 예기치 않은 버그나 오작동의 위험을 크게 줄인다.

이번 프로젝트인 ‘키티즈’의 경우, ‘먹는 중’, ‘노는 중’, ‘부스터 사용 중’, ‘레벨업 중’ 등 다양한 명확한 상태가 존재한다. 만약 기존 React의 useState나 Zustand로만 상태를 관리할 경우, 각 상태에 종속된 로직을 분리하기 어려워 특정 상태를 수정할 때마다 다른 상태의 정상 작동 여부까지 전부 확인해야 한다. 그러나 XState로 각 상태의 로직을 완전히 격리하면 이러한 어려움을 근본적으로 방지할 수 있다.

무한 상태 머신(Infinite State Machine, React useState 등)
───────────────────────────────────────────
   상태 A ────┐
     │      │ 사용자 입력/조건
     ▼      │
   상태 B ────┤
     │      │
     ▼      │
   상태 C ────┤ (모든 상태 간 자유로운 이동 가능)
     │      │
     ▼      │
   상태 N ────┘ (상태 개수가 무한에 가까우며, 전환 조건 불명확)
───────────────────────────────────────────
⛔️ 단점: 상태 전환 규칙이 불명확하여 관리가 어렵고 복잡해짐.


유한 상태 머신(Finite State Machine, XState)
───────────────────────────────────────────
      ┌────────────┐        ┌──────────┐
      │ 상태 A(대기) │───────▶│ 상태 B(공격)│
      └────────────┘        └──────────┘
         ▲  │                 │  ▲
         │  │                 │  │
         │  ▼                 ▼  │
      ┌────────────┐        ┌────────────┐
      │ 상태 D(방어) │◀───────│ 상태 C(이동)  │
      └────────────┘        └────────────┘
───────────────────────────────────────────
✅ 장점: 명확히 정의된 상태와 상태 간 전환 규칙이 존재하여, 상태를 관리하기 쉽고 오류 발생 가능성을 크게 줄임.

2. 제어권 역전(Inversion of Control): 자동 진행의 편의성

게임과 일반적인 웹 애플리케이션의 가장 큰 차이점은 ‘자동 진행’ 시나리오가 빈번하게 존재한다는 점이다. 예를 들어 캐릭터가 레벨업했을 때, 또는 특정 이벤트가 완료된 후 사용자의 추가 입력 없이도 게임 상태가 자동으로 다음 단계로 전환되거나, 비즈니스 로직에 따라서 단계를 건너뛰거나 단계 진행을 분기 처리 하거나, 특정 입력(예를 들면 클릭 이벤트)만 허용하는 등의 특별한 흐름이 필요하다.

이러한 자동 진행 흐름을 개발자가 수동적으로 직접 관리하는 것은 매우 복잡하고 번거로운 일이다. XState는 이런 상황에서 탁월한 장점을 발휘한다. 상태 흐름에 대한 제어권을 사용자가 아닌 XState의 머신이 가져가기 때문에, 특정 상태 진입 시 자동으로 다음 상태로 전환되는 로직을 매우 간편하게 구현할 수 있다. 이로써 React는 렌더링과 사용자 이벤트 처리를 담당하고, XState는 상태 변경에 따른 비즈니스 로직을 담당하도록 역할을 분리할 수 있다.

11키티즈의 경우, 캐릭터가 ‘레벨업’ 상태에 도달하면 XState machine에 미리 선언한 상태 전환 규칙에 따라서 필요시 ‘보상 지급’ 상태로 전환되도록 선언적으로 정의할 수 있다. 이 자동화된 전환을 XState가 자체적으로 관리하므로, 개발자는 간단히 상태 흐름과 분기 처리를 선언적으로 정의하면 된다. 이 덕분에 게임의 자동 진행 이벤트를 명료하고 효율적으로 개발할 수 있다.

사용자(User)                            │            XState 상태 머신
──────────────────────────────────────┼─────────────────────────────────────
                                      │
[사용자 입력]                            │
(클릭, 터치 등)───이벤트 전달──────────────▶│───┐
                                      │   │ 이벤트 수신
                                      │   ▼
                                      │┌────────────────────────┐
                                      ││   이벤트 처리 및 상태 결정   │
                                      ││ (상태 머신의 선언적 규칙 적용)│
                                      │└─────────┬──────────────┘
                                      │          │
                                      │          ▼
                                      │┌─────────────────────────┐
                                      ││     현재 상태 결정          │
                                      ││ (예: 대기, 레벨업, 보상 지급) │
                                      │└─────────┬───────────────┘
                                      │          │
                                      │          ▼
                                      │┌───────────────────────┐
                                      ││   상태 전환 로직 실행      │
                                      ││ (자동 전환, 분기 처리 등)  │
                                      │└─────────┬─────────────┘
                                      │          │
                                      │          │
                                      │◀─────────상태 업데이트
                                      │
┌───────────────────────────────────┐ │
│React 컴포넌트(UI 렌더링, 애니메이션 등)  │ │
└───────────────────────────────────┘ │
              │                       │
              ▼                       │
[사용자 화면에서 상태 확인 및 입력]──────────▶│───────────┐
(새로운 이벤트 발생 시 반복)                │           │
                                      │           ▼
                                      │┌───────────────────────┐
                                      ││   상태 전환 로직 실행      │
                                      ││ (자동 전환, 분기 처리 등)  │
                                      │└─────────┬─────────────┘
                                      │          │
                                      │          │
                                      │◀─────────상태 업데이트                                      
┌───────────────────────────────────┐ │
│React 컴포넌트(UI 렌더링, 애니메이션 등)  │ │
└───────────────────────────────────┘ │                                      
──────────────────────────────────────┼─────────────────────────────────────
       React가 담당하는 로직              │     XState가 담당하는 로직

3. XState 사용 시 주의할 점

XState는 매우 유용하지만, 몇 가지 주의할 점이 있다.

XState에 모든 비즈니스 로직을 몰아넣자

유한 상태 머신에서 관리하는 상태와 직접적으로 연관된 로직이라면, 전부 XState의 머신 내부에 집중시키는 것이 좋다. 만약 특정 비즈니스 로직을 변경하거나 어떤 상태를 더 이상 사용하지 않게 되었을 때, 각 React 컴포넌트에 로직이 산재해 있다면 모든 컴포넌트를 일일이 확인하고 수정해야 하는 번거로움이 발생한다. 모든 상태 관련 로직을 XState에 위임하고 격리하면 이러한 불필요한 비용을 효과적으로 줄일 수 있다.

상태 머신(state machine)은 가급적 작게 만들자

XState는 개발 생산성을 크게 향상시켜 주지만, 지나치게 큰 하나의 머신에 모든 상태를 몰아넣으면 디버깅이 어려워진다. 머신이 복잡해질수록 특정 상황에서 디버깅을 시작하기 위한 준비 과정이 매우 길어지기 때문이다. FE 애플리케이션에서의 일반적인 디버깅(예: 버튼 클릭 등)에 비해 훨씬 많은 수고가 요구된다. 따라서 상태 머신을 작게 나누어 관리하고, 필요한 경우 여러 개의 상태 머신을 조합하여 사용하도록 하자.

결론

XState는 게임 개발에서 요구되는 명확한 상태 관리와 자동 진행 로직 구현에 매우 적합한 도구다. 일반적인 React 상태 관리(useState, Zustand, Redux 등)의 복잡성과 불명확성을 해소하며, 게임 개발의 특수한 요구사항을 효과적으로 충족시킨다.

이번 11키티즈 프로젝트에서는 XState를 적극 활용하여 명확한 상태 관리, 제어권 역전을 통한 자동 진행 구현 등을 통해 개발 생산성과 품질, 유지보수성을 모두 성공적으로 높일 수 있었다.

이 글이 XState 도입을 고민하는 개발자에게 유용한 참고자료가 되기를 바란다.

EOD

20250416