f8b21af4be
10_Wiki/Topics 대규모 정리: - 오류 캡처/미완성 stub 문서 227개 제거 - 교차폴더 중복 43클러스터 병합 (63파일 → redirect) - 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건 - 카테고리 MOC 6개 신규 생성 - Graph 섹션 미해결 related-keyword 링크 10,058건 제거 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.1 KiB
6.1 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-상태-머신-state-machine-모델링-및-redux- | 상태 머신 (State Machine) 모델링 및 Redux 액션/리듀서 설계 | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
상태 머신 (State Machine) 모델링 및 Redux 액션/리듀서 설계
매 한 줄
"매 impossible state 의 unrepresentable 화". 매 finite state machine (FSM) 는 explicit state + event + transition 의 enumerate. Redux reducer 는 매 (state, action) → state 의 pure function — 매 FSM 와 isomorphic. 2026 년 매 XState 5 + RTK 의 combine 패턴 의 standard.
매 핵심
매 FSM 5-tuple
- States (Q): enumerable set —
idle | loading | success | error. - Events (Σ): external triggers —
FETCH | RESOLVE | REJECT. - Transitions (δ):
Q × Σ → Q— 매 partial function. - Initial state (q₀):
idle. - Final states (F): optional — terminal nodes.
매 Redux 와 mapping
- Reducer = δ:
(state, action) => newState의 pure transition. - Action = Σ event: typed discriminated union.
- Store state = Q: 매 status field 의 enum.
- Selector: 매 derived view —
isLoading = state.status === 'loading'.
매 응용
- Form wizard — multi-step flow 의 state 의 explicit.
- Data fetching — idle/loading/success/error 의 4-state.
- Auth flow — anonymous/authenticating/authenticated/expired.
💻 패턴
Discriminated union state
type FetchState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
// 매 impossible state ('loading' + data) 의 unrepresentable.
RTK slice = FSM reducer
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
const userSlice = createSlice({
name: 'user',
initialState: { status: 'idle' } as FetchState<User>,
reducers: {
fetch: (state) => {
if (state.status === 'idle' || state.status === 'error') {
return { status: 'loading' };
}
return state; // ignore invalid transition
},
resolve: (_, action: PayloadAction<User>) => ({
status: 'success',
data: action.payload,
}),
reject: (_, action: PayloadAction<Error>) => ({
status: 'error',
error: action.payload,
}),
},
});
Transition guard table
const TRANSITIONS = {
idle: { FETCH: 'loading' },
loading: { RESOLVE: 'success', REJECT: 'error' },
success: { FETCH: 'loading' },
error: { FETCH: 'loading' },
} as const;
function transition<S extends keyof typeof TRANSITIONS>(
state: S,
event: string
): string {
return (TRANSITIONS[state] as any)[event] ?? state;
}
XState 5 + Redux integration
import { createMachine, createActor } from 'xstate';
const fetchMachine = createMachine({
id: 'fetch',
initial: 'idle',
states: {
idle: { on: { FETCH: 'loading' } },
loading: {
invoke: {
src: 'fetchUser',
onDone: { target: 'success', actions: 'storeData' },
onError: 'error',
},
},
success: { on: { REFRESH: 'loading' } },
error: { on: { RETRY: 'loading' } },
},
});
const actor = createActor(fetchMachine).start();
actor.subscribe((snapshot) => store.dispatch({ type: 'fsm/sync', payload: snapshot.value }));
Hierarchical (nested) state
// 매 auth flow — 매 sub-state machine.
const authMachine = createMachine({
initial: 'unauthenticated',
states: {
unauthenticated: {
initial: 'idle',
states: {
idle: { on: { LOGIN: 'submitting' } },
submitting: { on: { SUCCESS: '#auth.authenticated', FAIL: 'idle' } },
},
},
authenticated: {
on: { LOGOUT: 'unauthenticated' },
},
},
}, { id: 'auth' });
Parallel state regions
const editorMachine = createMachine({
type: 'parallel',
states: {
document: { initial: 'clean', states: { clean: {}, dirty: {} } },
network: { initial: 'online', states: { online: {}, offline: {} } },
},
});
// 매 state = (document, network) 의 cross product — explicit.
Test as transition table
test.each([
['idle', 'FETCH', 'loading'],
['loading', 'RESOLVE', 'success'],
['loading', 'REJECT', 'error'],
['success', 'FETCH', 'loading'],
])('transition %s --%s--> %s', (from, event, to) => {
expect(transition(from, event)).toBe(to);
});
매 결정 기준
| 상황 | Approach |
|---|---|
| Simple async (fetch) | RTK createAsyncThunk + discriminated union |
| Multi-step wizard | XState machine |
| Complex auth | XState hierarchical machine |
| Parallel concerns | XState parallel states |
| Pure UI toggle | useState (not Redux) |
기본값: RTK + discriminated union state. 복잡 시 XState 5.
🔗 Graph
- 부모: 프론트엔드_및_UIUX_표준
- 변형: XState
- 응용: Data Fetching
- Adjacent: Discriminated Union · Pure Function · Event Sourcing
🤖 LLM 활용
언제: state 가 3+ 개 + transition 의 explicit rule 의 필요 시. 언제 X: simple boolean toggle 또는 single-shot async — 매 overkill.
❌ 안티패턴
- Boolean explosion:
isLoading + isError + isSuccess— impossible state (true+true) 의 representable. - Implicit transition: reducer 안 valid state check 의 X — 매 invalid transition 의 silently 발생.
- God reducer: 매 모든 logic 의 한 reducer — 매 split.
- Side effect in reducer:
fetch()의 reducer 내부 — 매 thunk/saga/middleware 사용.
🧪 검증 / 중복
- Verified (Hopcroft & Ullman Automata Theory; Redux docs; XState v5 docs 2026).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — FSM↔Redux mapping + XState 5 patterns |