--- 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 ; if (state.matches('error')) return ; if (state.matches('success')) return ; return ; } ``` ### 매 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 + 결정 기준 |