---
id: wiki-2026-0508-api-응답-모델링-및-상태-머신-state-machine
title: API Response Modeling + State Machine
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [State Machine design, XState, FSM, async state]
duplicate_of: none
source_trust_level: B
confidence_score: 0.85
verification_status: applied
tags: [state-machine, xstate, fsm, typescript, async-state, discriminated-union]
raw_sources: []
last_reinforced: 2026-05-09
github_commit: pending
---

# API Response Modeling + State Machine

## 📌 한 줄 통찰
> **Discriminated union 의 baseline + state machine (XState) 의 complex flow**. 매 invalid state + invalid transition 의 prevent. 매 actor model 의 modern.

## 📖 핵심

### 매 spectrum

#### Simple state (1-3 state)
- Discriminated union 충분.
- React useState.

#### Medium (4-6 state, parallel)
- useReducer / Zustand.
- Manual transition.

#### Complex (10+ state, hierarchy)
- XState / Robot.
- Visual editor.
- Statecharts.

### 매 statechart concept (Harel)

#### Hierarchical state
```
Authenticated:
  - Browsing
  - Editing
  - Submitting
Unauthenticated:
  - LoggingIn
  - SigningUp
```

→ 매 sub-state 의 share parent transition.

#### Parallel state
```
[Editing] || [Saving]
```

→ 매 simultaneously.

#### History state
- 매 last state 의 remember.
- 매 modal close → previous state.

#### Guard
- 매 transition 의 condition.

#### Action
- 매 transition 의 side effect.

### XState (TS)

#### Machine definition
```ts
import { createMachine, assign } from 'xstate';

const fetchMachine = createMachine({
  id: 'fetch',
  initial: 'idle',
  context: { data: null, error: null },
  states: {
    idle: {
      on: { FETCH: 'loading' }
    },
    loading: {
      invoke: {
        src: 'fetchData',
        onDone: { target: 'success', actions: assign({ data: ({ event }) => event.output }) },
        onError: { target: 'error', actions: assign({ error: ({ event }) => event.error }) },
      }
    },
    success: {
      on: { REFETCH: 'loading' }
    },
    error: {
      on: { RETRY: 'loading' }
    },
  },
});
```

#### Usage (React)
```tsx
import { useMachine } from '@xstate/react';

function Component() {
  const [state, send] = useMachine(fetchMachine, {
    services: { fetchData: () => api.fetch() }
  });
  
  if (state.matches('loading')) return <Spinner />;
  if (state.matches('error')) return <Error msg={state.context.error} />;
  if (state.matches('success')) return <Data data={state.context.data} />;
  return <button onClick={() => send({ type: 'FETCH' })}>Load</button>;
}
```

### 매 advantage

#### Visual
- 매 state diagram 의 generate.
- 매 stakeholder 의 communicate.

#### Test
- 매 state + transition 의 explicit.
- 매 path 의 enumerate.

#### Documentation
- 매 code 의 self-documenting.

#### Refactor safety
- 매 invalid transition 의 compile fail.

### 매 limit

#### Learning curve
- 매 statechart 의 unfamiliar.
- 매 boilerplate.

#### Over-engineering
- 매 simple state 의 useState 의 enough.

#### XState 의 specific syntax
- 매 vendor lock-in.

### Alternative

#### Robot
- 매 lighter weight.
- 매 simpler API.

#### useReducer (React)
- 매 native.
- 매 simple state machine.

#### Zustand + slice
- 매 store-based.
- 매 manual transition.

### 매 use case

#### Complex form
- 매 multi-step.
- 매 validation per step.
- 매 conditional branching.

#### Authentication flow
- 매 login → 2FA → success.
- 매 multiple path.

#### Game state
- 매 menu / playing / paused / game-over.

#### Real-time (chat, video call)
- 매 connecting / connected / disconnected / reconnecting.

#### Workflow
- 매 multi-stage approval.

## 💻 Code

### Discriminated union (simple)
```ts
type State =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: User }
  | { status: 'error'; message: string };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'FETCH':
      return { status: 'loading' };
    case 'SUCCESS':
      return { status: 'success', data: action.payload };
    case 'ERROR':
      return { status: 'error', message: action.error };
  }
}
```

### useReducer
```tsx
function Component() {
  const [state, dispatch] = useReducer(reducer, { status: 'idle' });
  
  useEffect(() => {
    dispatch({ type: 'FETCH' });
    api.fetch()
      .then(data => dispatch({ type: 'SUCCESS', payload: data }))
      .catch(e => dispatch({ type: 'ERROR', error: e.message }));
  }, []);
  
  // ...
}
```

### XState (full)
```ts
import { setup, createMachine } from 'xstate';

const machine = setup({
  types: { context: {}, events: {} as { type: 'NEXT' } | { type: 'PREV' } },
  guards: {
    canProceed: ({ context }) => context.formValid === true,
  },
}).createMachine({
  id: 'wizard',
  initial: 'step1',
  context: { formValid: false },
  states: {
    step1: {
      on: { NEXT: { target: 'step2', guard: 'canProceed' } }
    },
    step2: {
      on: { NEXT: 'step3', PREV: 'step1' }
    },
    step3: {
      on: { PREV: 'step2', SUBMIT: 'submitting' }
    },
    submitting: {
      invoke: {
        src: 'submitForm',
        onDone: 'success',
        onError: 'step3',
      }
    },
    success: { type: 'final' },
  },
});
```

### Hierarchical
```ts
const auth = createMachine({
  id: 'auth',
  initial: 'unauthenticated',
  states: {
    unauthenticated: {
      initial: 'login',
      states: {
        login: { on: { SIGNUP: 'signup' } },
        signup: { on: { LOGIN: 'login' } },
      },
      on: { AUTHENTICATED: 'authenticated' }
    },
    authenticated: {
      initial: 'browsing',
      states: {
        browsing: { on: { EDIT: 'editing' } },
        editing: { on: { SAVE: 'saving' } },
        saving: { on: { DONE: 'browsing' } },
      },
      on: { LOGOUT: 'unauthenticated' }
    },
  },
});
```

### Visual (XState VS Code extension)
- 매 .machine.ts file 의 visual.
- 매 state + transition 의 graphical.

### Testing
```ts
import { createActor } from 'xstate';

test('login flow', () => {
  const actor = createActor(authMachine).start();
  
  actor.send({ type: 'SIGNUP' });
  expect(actor.getSnapshot().value).toBe('unauthenticated.signup');
  
  actor.send({ type: 'LOGIN' });
  expect(actor.getSnapshot().value).toBe('unauthenticated.login');
  
  actor.send({ type: 'AUTHENTICATED' });
  expect(actor.getSnapshot().value).toBe('authenticated.browsing');
});
```

## 🤔 결정 기준

| Complexity | Tool |
|---|---|
| < 4 state | useState + discriminated union |
| 4-8 simple | useReducer |
| 4-8 complex | XState (lite) |
| 10+ hierarchical | XState (full) |
| Cross-component | XState actor |
| Workflow / multi-step | XState 추천 |

**기본값**: Discriminated union + useReducer. 매 complex flow 의 XState.

## 🔗 Graph
- 부모: [[State Management]] · [[API-Design]]
- 변형: [[XState]]
- 응용: [[FSM]]
- Adjacent: [[Discriminated-Union]] · [[useReducer]] · [[Zustand]]

## 🤖 LLM 활용
**언제**: 매 complex async flow. 매 multi-step form / wizard. 매 game state.
**언제 X**: 매 simple toggle. 매 trivial component state.

## ❌ 안티패턴
- **Boolean explosion** (isLoading, isError, isSuccess separate): invalid combination.
- **No state machine + complex flow**: bug 폭발.
- **State machine + simple state**: over-engineer.
- **No exhaustive check**: missed transition.
- **Mixed concerns (UI + business)**: 매 separate.

## 🧪 검증 / 중복
- Verified (XState docs, Statecharts.dev).
- 신뢰도 B.
- Related: [[State Modeling and API Responses]] (closely related).

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-09 | Cleanup — XState code + statechart + 결정 기준 |
