diff --git a/.docs/dispatch-async/06-setup-guide.md b/.docs/dispatch-async/06-setup-guide.md new file mode 100644 index 00000000..f7260ea0 --- /dev/null +++ b/.docs/dispatch-async/06-setup-guide.md @@ -0,0 +1,396 @@ +# 설정 가이드 + +## 📋 목차 + +1. [초기 설정](#초기-설정) +2. [파일 구조 확인](#파일-구조-확인) +3. [설정 순서](#설정-순서) +4. [검증 방법](#검증-방법) +5. [트러블슈팅](#트러블슈팅) + +--- + +## 초기 설정 + +### 1️⃣ 필수: panelQueueMiddleware 등록 + +큐 기반 패널 액션 시스템을 사용하려면 **반드시** Redux store에 미들웨어를 등록해야 합니다. + +#### 파일 위치 +`com.twin.app.shoptime/src/store/store.js` + +#### 수정 전 +```javascript +import { applyMiddleware, combineReducers, createStore } from 'redux'; +import thunk from 'redux-thunk'; + +import { autoCloseMiddleware } from '../middleware/autoCloseMiddleware'; +import { panelHistoryMiddleware } from '../middleware/panelHistoryMiddleware'; +// panelQueueMiddleware import 없음! + +// ... reducers ... + +export const store = createStore( + rootReducer, + applyMiddleware(thunk, panelHistoryMiddleware, autoCloseMiddleware) + // panelQueueMiddleware 등록 없음! +); +``` + +#### 수정 후 +```javascript +import { applyMiddleware, combineReducers, createStore } from 'redux'; +import thunk from 'redux-thunk'; + +import { autoCloseMiddleware } from '../middleware/autoCloseMiddleware'; +import { panelHistoryMiddleware } from '../middleware/panelHistoryMiddleware'; +import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; // ← 추가 + +// ... reducers ... + +export const store = createStore( + rootReducer, + applyMiddleware( + thunk, + panelHistoryMiddleware, + autoCloseMiddleware, + panelQueueMiddleware // ← 추가 (맨 마지막 위치) + ) +); +``` + +### 2️⃣ 미들웨어 등록 순서 + +미들웨어 등록 순서는 다음과 같습니다: + +```javascript +applyMiddleware( + thunk, // 1. Redux-thunk (비동기 액션 지원) + panelHistoryMiddleware, // 2. 패널 히스토리 관리 + autoCloseMiddleware, // 3. 자동 닫기 처리 + panelQueueMiddleware // 4. 패널 큐 처리 (맨 마지막) +) +``` + +**중요**: `panelQueueMiddleware`는 **맨 마지막**에 위치해야 합니다! +- 다른 미들웨어들이 먼저 액션을 처리한 후 +- 큐 미들웨어가 큐 관련 액션을 감지하고 처리합니다 + +--- + +## 파일 구조 확인 + +### 필수 파일들이 모두 존재하는지 확인 + +```bash +# 프로젝트 루트에서 실행 +ls -la com.twin.app.shoptime/src/middleware/panelQueueMiddleware.js +ls -la com.twin.app.shoptime/src/actions/queuedPanelActions.js +ls -la com.twin.app.shoptime/src/utils/dispatchHelper.js +ls -la com.twin.app.shoptime/src/utils/asyncActionUtils.js +ls -la com.twin.app.shoptime/src/reducers/panelReducer.js +``` + +### 예상 출력 +``` +-rw-r--r-- 1 user user 2063 Nov 10 06:32 .../panelQueueMiddleware.js +-rw-r--r-- 1 user user 13845 Nov 06 10:15 .../queuedPanelActions.js +-rw-r--r-- 1 user user 12345 Nov 05 14:20 .../dispatchHelper.js +-rw-r--r-- 1 user user 10876 Nov 06 10:30 .../asyncActionUtils.js +-rw-r--r-- 1 user user 25432 Nov 06 11:00 .../panelReducer.js +``` + +### 파일이 없다면? + +```bash +# 최신 코드를 pull 받으세요 +git fetch origin +git pull origin +``` + +--- + +## 설정 순서 + +### Step 1: 미들웨어 import 추가 + +**파일**: `src/store/store.js` + +```javascript +import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; +``` + +### Step 2: applyMiddleware에 추가 + +```javascript +export const store = createStore( + rootReducer, + applyMiddleware( + thunk, + panelHistoryMiddleware, + autoCloseMiddleware, + panelQueueMiddleware // ← 추가 + ) +); +``` + +### Step 3: 저장 및 빌드 + +```bash +# 파일 저장 후 +npm run build +# 또는 개발 서버 재시작 +npm start +``` + +### Step 4: 브라우저 콘솔 확인 + +브라우저 개발자 도구(F12)를 열고 다음과 같은 로그가 보이는지 확인: + +``` +[panelQueueMiddleware] 🚀 ACTION_ENQUEUED +[panelQueueMiddleware] ⚡ STARTING_QUEUE_PROCESS +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +[panelReducer] 🟡 PROCESSING_QUEUE_ITEM +[panelReducer] ✅ QUEUE_ITEM_PROCESSED +``` + +--- + +## 검증 방법 + +### 방법 1: 콘솔 로그 확인 + +큐 시스템을 사용하는 액션을 dispatch하면 다음과 같은 로그가 출력됩니다: + +```javascript +import { pushPanelQueued } from '../actions/queuedPanelActions'; +import { panel_names } from '../utils/Config'; + +dispatch(pushPanelQueued({ name: panel_names.SEARCH_PANEL })); +``` + +**예상 로그**: +``` +[panelQueueMiddleware] 🚀 ACTION_ENQUEUED { action: 'PUSH_PANEL', queueId: 'queue_item_1_1699999999999' } +[panelQueueMiddleware] ⚡ STARTING_QUEUE_PROCESS +[panelReducer] 🟡 PROCESS_PANEL_QUEUE { isProcessing: false, queueLength: 1 } +[panelReducer] 🟡 PROCESSING_QUEUE_ITEM { action: 'PUSH_PANEL', queueId: 'queue_item_1_1699999999999', remainingQueueLength: 0 } +[panelReducer] 🔵 PUSH_PANEL START { newPanelName: 'SEARCH_PANEL', currentPanels: [...], duplicatable: false } +[panelReducer] 🔵 PUSH_PANEL END { resultPanels: [...], lastAction: 'push' } +[panelReducer] ✅ QUEUE_ITEM_PROCESSED { action: 'PUSH_PANEL', queueId: 'queue_item_1_1699999999999', processingTime: 2 } +``` + +### 방법 2: Redux DevTools 확인 + +Redux DevTools를 사용하여 액션 흐름을 확인: + +1. Chrome 확장 프로그램: Redux DevTools 설치 +2. 개발자 도구에서 "Redux" 탭 선택 +3. 다음 액션들이 순서대로 dispatch되는지 확인: + - `ENQUEUE_PANEL_ACTION` + - `PROCESS_PANEL_QUEUE` + - `PUSH_PANEL` (또는 다른 패널 액션) + +### 방법 3: State 확인 + +Redux state를 확인하여 큐 관련 상태가 정상적으로 업데이트되는지 확인: + +```javascript +// 콘솔에서 실행 +store.getState().panels +``` + +**예상 출력**: +```javascript +{ + panels: [...], // 실제 패널들 + lastPanelAction: 'push', + + // 큐 관련 상태 + panelActionQueue: [], // 처리 대기 중인 큐 (처리 후 비어있음) + isProcessingQueue: false, + queueError: null, + queueStats: { + totalProcessed: 1, + failedCount: 0, + averageProcessingTime: 2.5 + }, + + // 비동기 액션 관련 + asyncActions: {}, + completedAsyncActions: [], + failedAsyncActions: [] +} +``` + +--- + +## 트러블슈팅 + +### 문제 1: 큐가 처리되지 않음 + +#### 증상 +```javascript +dispatch(pushPanelQueued({ name: panel_names.SEARCH_PANEL })); +// 아무 일도 일어나지 않음 +// 로그도 출력되지 않음 +``` + +#### 원인 +panelQueueMiddleware가 등록되지 않음 + +#### 해결 방법 +1. `store.js` 파일 확인: + ```javascript + // import가 있는지 확인 + import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; + + // applyMiddleware에 추가되어 있는지 확인 + applyMiddleware(..., panelQueueMiddleware) + ``` + +2. 파일 저장 후 앱 재시작 +3. 브라우저 캐시 삭제 (Ctrl+Shift+R 또는 Cmd+Shift+R) + +### 문제 2: 미들웨어 파일을 찾을 수 없음 + +#### 증상 +``` +Error: Cannot find module '../middleware/panelQueueMiddleware' +``` + +#### 원인 +파일이 존재하지 않거나 경로가 잘못됨 + +#### 해결 방법 +1. 파일 존재 확인: + ```bash + ls -la com.twin.app.shoptime/src/middleware/panelQueueMiddleware.js + ``` + +2. 파일이 없다면 최신 코드 pull: + ```bash + git fetch origin + git pull origin main + ``` + +3. 여전히 없다면 커밋 확인: + ```bash + git log --oneline --grep="panelQueueMiddleware" + # 5bd2774 [251106] feat: Queued Panel functions + ``` + +### 문제 3: 로그는 보이는데 패널이 열리지 않음 + +#### 증상 +``` +[panelQueueMiddleware] 🚀 ACTION_ENQUEUED +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +[panelReducer] ✅ QUEUE_ITEM_PROCESSED +// 하지만 패널이 화면에 표시되지 않음 +``` + +#### 원인 +UI 렌더링 문제 (Redux는 정상 작동) + +#### 해결 방법 +1. Redux state 확인: + ```javascript + console.log(store.getState().panels.panels); + // 패널이 배열에 추가되었는지 확인 + ``` + +2. 패널 컴포넌트 렌더링 로직 확인 +3. React DevTools로 컴포넌트 트리 확인 + +### 문제 4: 타입 에러 + +#### 증상 +``` +Error: Cannot read property 'type' of undefined +ReferenceError: types is not defined +``` + +#### 원인 +actionTypes.js에 필요한 타입이 정의되지 않음 + +#### 해결 방법 +1. `src/actions/actionTypes.js` 확인: + ```javascript + export const types = { + // ... 기존 타입들 ... + + // 큐 관련 타입들 + ENQUEUE_PANEL_ACTION: 'ENQUEUE_PANEL_ACTION', + PROCESS_PANEL_QUEUE: 'PROCESS_PANEL_QUEUE', + CLEAR_PANEL_QUEUE: 'CLEAR_PANEL_QUEUE', + SET_QUEUE_PROCESSING: 'SET_QUEUE_PROCESSING', + + // 비동기 액션 타입들 + ENQUEUE_ASYNC_PANEL_ACTION: 'ENQUEUE_ASYNC_PANEL_ACTION', + COMPLETE_ASYNC_PANEL_ACTION: 'COMPLETE_ASYNC_PANEL_ACTION', + FAIL_ASYNC_PANEL_ACTION: 'FAIL_ASYNC_PANEL_ACTION', + }; + ``` + +2. 없다면 추가 후 저장 + +### 문제 5: 순서가 여전히 보장되지 않음 + +#### 증상 +```javascript +dispatch(pushPanelQueued({ name: 'PANEL_1' })); +dispatch(pushPanelQueued({ name: 'PANEL_2' })); +// PANEL_2가 먼저 열림 +``` + +#### 원인 +일반 `pushPanel`과 `pushPanelQueued`를 혼용 + +#### 해결 방법 +순서를 보장하려면 **모두** queued 버전 사용: +```javascript +// ❌ 잘못된 사용 +dispatch(pushPanel({ name: 'PANEL_1' })); // 일반 버전 +dispatch(pushPanelQueued({ name: 'PANEL_2' })); // 큐 버전 + +// ✅ 올바른 사용 +dispatch(pushPanelQueued({ name: 'PANEL_1' })); +dispatch(pushPanelQueued({ name: 'PANEL_2' })); + +// 또는 +dispatch(enqueueMultiplePanelActions([ + pushPanelQueued({ name: 'PANEL_1' }), + pushPanelQueued({ name: 'PANEL_2' }) +])); +``` + +--- + +## 빠른 체크리스트 + +설정이 완료되었는지 빠르게 확인: + +- [ ] `src/store/store.js`에 `import panelQueueMiddleware` 추가됨 +- [ ] `applyMiddleware`에 `panelQueueMiddleware` 추가됨 (맨 마지막 위치) +- [ ] 파일 저장 및 앱 재시작 +- [ ] 브라우저 콘솔에서 큐 관련 로그 확인 +- [ ] Redux DevTools에서 액션 흐름 확인 +- [ ] Redux state에서 큐 관련 상태 확인 + +모든 항목이 체크되었다면 설정 완료! 🎉 + +--- + +## 참고 자료 + +- [README.md](./README.md) - 전체 개요 +- [04-solution-queue-system.md](./04-solution-queue-system.md) - 큐 시스템 상세 설명 +- [05-usage-patterns.md](./05-usage-patterns.md) - 사용 패턴 및 예제 +- [07-changelog.md](./07-changelog.md) - 변경 이력 + +--- + +**작성일**: 2025-11-10 +**최종 수정일**: 2025-11-10 diff --git a/.docs/dispatch-async/07-changelog.md b/.docs/dispatch-async/07-changelog.md new file mode 100644 index 00000000..130ba5e2 --- /dev/null +++ b/.docs/dispatch-async/07-changelog.md @@ -0,0 +1,314 @@ +# 변경 이력 (Changelog) + +## [2025-11-10] - 미들웨어 등록 및 문서 개선 + +### 🔧 수정 (Fixed) + +#### store.js - panelQueueMiddleware 등록 +**커밋**: `c12cc91 [수정] panelQueueMiddleware 등록 및 문서 업데이트` + +**문제**: +- panelQueueMiddleware가 store.js에 등록되어 있지 않았음 +- 큐 시스템이 작동하지 않는 치명적인 문제 +- `ENQUEUE_PANEL_ACTION` dispatch 시 자동으로 `PROCESS_PANEL_QUEUE`가 실행되지 않음 + +**해결**: +```javascript +// src/store/store.js +import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; + +export const store = createStore( + rootReducer, + applyMiddleware(thunk, panelHistoryMiddleware, autoCloseMiddleware, panelQueueMiddleware) +); +``` + +**영향**: +- ✅ 큐 기반 패널 액션 시스템이 정상 작동 +- ✅ 패널 액션 순서 보장 +- ✅ 비동기 패널 액션 자동 처리 + +### 📝 문서 (Documentation) + +#### README.md +- "설치 및 설정" 섹션 추가 +- panelQueueMiddleware 등록 필수 사항 강조 +- 등록하지 않으면 큐 시스템이 작동하지 않는다는 경고 추가 + +#### 04-solution-queue-system.md +- "사전 요구사항" 섹션 추가 +- 미들웨어 등록 코드 예제 포함 +- `src/store/store.js`를 관련 파일에 추가 + +#### 05-usage-patterns.md +- "초기 설정 확인사항" 체크리스트 추가 +- panelQueueMiddleware 등록 여부를 최우선 확인 항목으로 배치 + +--- + +## [2025-11-10] - 초기 문서 작성 + +### ✨ 추가 (Added) + +#### 문서 작성 +**커밋**: `f75860c [문서화] Dispatch 비동기 처리 순서 보장 솔루션 문서 작성` + +dispatch 비동기 처리 순서 보장 문제와 해결 방법을 체계적으로 정리한 문서 세트: + +1. **README.md** + - 전체 개요 및 목차 + - 주요 솔루션 요약 + - 관련 파일 목록 + - 커밋 히스토리 + +2. **01-problem.md** + - 문제 상황 및 원인 분석 + - Redux-thunk에서 dispatch 순서가 보장되지 않는 이유 + - 실제 발생 가능한 버그 시나리오 + - 기존 해결 방법의 한계 + +3. **02-solution-dispatch-helper.md** + - dispatchHelper.js 솔루션 설명 + - 5가지 헬퍼 함수 상세 설명: + - `createSequentialDispatch` + - `createApiThunkWithChain` + - `withLoadingState` + - `createConditionalDispatch` + - `createParallelDispatch` + - Before/After 코드 비교 + - 실제 사용 예제 + +4. **03-solution-async-utils.md** + - asyncActionUtils.js 솔루션 설명 + - API 성공 기준 명확화 (HTTP 200-299 + retCode 0/'0') + - Promise 체인 보장 방법 (reject 없이 resolve만 사용) + - 주요 함수 설명: + - `isApiSuccess` + - `fetchApi` + - `tAxiosToPromise` + - `wrapAsyncAction` + - `withTimeout` + - `executeParallelAsyncActions` + +5. **04-solution-queue-system.md** + - 큐 기반 패널 액션 시스템 설명 + - 기본 패널 액션 (pushPanelQueued, popPanelQueued 등) + - 비동기 패널 액션 (enqueueAsyncPanelAction) + - API 호출 후 패널 액션 (createApiWithPanelActions) + - 비동기 액션 시퀀스 (createAsyncPanelSequence) + - panelQueueMiddleware 동작 원리 + - 리듀서 상태 구조 + +6. **05-usage-patterns.md** + - 솔루션 선택 가이드 (의사결정 플로우차트) + - 솔루션 비교표 + - 공통 패턴 Before/After 비교 + - 실전 예제 5가지: + - 검색 기능 + - 장바구니 추가 + - 로그인 플로우 + - 다단계 폼 제출 + - 병렬 데이터 로딩 + - 마이그레이션 가이드 + - Best Practices + - 체크리스트 + +**문서 통계**: +- 총 6개 마크다운 파일 +- 약 3,000줄 +- 50개 이상의 코드 예제 +- Before/After 비교 20개 이상 + +--- + +## [2025-11-06] - 큐 시스템 구현 + +### ✨ 추가 (Added) + +#### Dispatch Queue Implementation +**커밋**: `f9290a1 [251106] fix: Dispatch Queue implementation` + +- `asyncActionUtils.js` 추가 + - Promise 기반 비동기 액션 처리 + - API 성공 기준 명확화 + - 타임아웃 지원 + +- `queuedPanelActions.js` 확장 + - 비동기 패널 액션 지원 + - API 호출 후 패널 액션 자동 실행 + - 비동기 액션 시퀀스 + +- `panelReducer.js` 확장 + - 큐 상태 관리 + - 비동기 액션 상태 추적 + - 큐 처리 통계 + +#### Queued Panel Functions +**커밋**: `5bd2774 [251106] feat: Queued Panel functions` + +- `queuedPanelActions.js` 초기 구현 + - 기본 큐 액션 (pushPanelQueued, popPanelQueued 등) + - 여러 액션 일괄 큐 추가 + - 패널 시퀀스 생성 + +- `panelQueueMiddleware.js` 추가 + - 큐 액션 자동 감지 + - 순차 처리 자동 시작 + - 연속 처리 지원 + +- `panelReducer.js` 큐 기능 추가 + - 큐 상태 관리 + - 큐 처리 로직 + - 큐 통계 수집 + +--- + +## [2025-11-05] - dispatch 헬퍼 함수 + +### ✨ 추가 (Added) + +#### dispatchHelper.js +**커밋**: `9490d72 [251105] feat: dispatchHelper.js` + +Promise 체인 기반의 dispatch 순차 실행 헬퍼 함수 모음: + +- `createSequentialDispatch` + - 여러 dispatch를 순차적으로 실행 + - Promise 체인으로 순서 보장 + - delay 옵션 지원 + - stopOnError 옵션 지원 + +- `createApiThunkWithChain` + - API 호출 후 dispatch 자동 체이닝 + - TAxios onSuccess/onFail 패턴 호환 + - response를 각 action에 전달 + - 에러 처리 action 지원 + +- `withLoadingState` + - 로딩 상태 자동 관리 + - changeAppStatus 자동 on/off + - 성공/에러 시 추가 dispatch 지원 + - loadingType 옵션 + +- `createConditionalDispatch` + - 조건에 따라 다른 dispatch 실행 + - getState() 결과 기반 분기 + - 배열 또는 단일 action 지원 + +- `createParallelDispatch` + - 여러 API를 병렬로 실행 + - Promise.all 사용 + - 로딩 상태 관리 옵션 + +--- + +## 관련 커밋 전체 목록 + +```bash +c12cc91 [수정] panelQueueMiddleware 등록 및 문서 업데이트 +f75860c [문서화] Dispatch 비동기 처리 순서 보장 솔루션 문서 작성 +f9290a1 [251106] fix: Dispatch Queue implementation +5bd2774 [251106] feat: Queued Panel functions +9490d72 [251105] feat: dispatchHelper.js +``` + +--- + +## 마이그레이션 가이드 + +### 기존 코드에서 새 솔루션으로 전환 + +#### 1단계: setTimeout 패턴 제거 + +```javascript +// Before +dispatch(action1()); +setTimeout(() => { + dispatch(action2()); +}, 0); + +// After +dispatch(createSequentialDispatch([action1(), action2()])); +``` + +#### 2단계: API 패턴 개선 + +```javascript +// Before +const onSuccess = (response) => { + dispatch({ type: types.ACTION_1, payload: response.data }); + dispatch(action2()); +}; +TAxios(..., onSuccess, onFail); + +// After +dispatch(createApiThunkWithChain( + (d, gs, onS, onF) => TAxios(d, gs, ..., onS, onF), + [ + (response) => ({ type: types.ACTION_1, payload: response.data }), + action2() + ] +)); +``` + +#### 3단계: 패널 액션을 큐 버전으로 전환 + +```javascript +// Before +dispatch(pushPanel({ name: panel_names.SEARCH })); + +// After +dispatch(pushPanelQueued({ name: panel_names.SEARCH })); +``` + +--- + +## Breaking Changes + +### 없음 + +모든 새로운 기능은 기존 코드와 완전히 호환됩니다: +- 기존 `pushPanel`, `popPanel` 등은 그대로 동작 +- 새로운 큐 버전은 선택적으로 사용 가능 +- 점진적 마이그레이션 가능 + +--- + +## 알려진 이슈 + +### 해결됨 + +1. **panelQueueMiddleware 미등록 문제** (2025-11-10 해결) + - 문제: 큐 시스템이 작동하지 않음 + - 해결: store.js에 미들웨어 등록 + +### 현재 이슈 + +없음 + +--- + +## 향후 계획 + +### 예정된 개선사항 + +1. **성능 최적화** + - 큐 처리 성능 모니터링 + - 대량 액션 처리 최적화 + +2. **에러 처리 강화** + - 더 상세한 에러 메시지 + - 에러 복구 전략 + +3. **개발자 도구** + - 큐 상태 시각화 + - 디버깅 도구 + +4. **테스트 코드** + - 단위 테스트 추가 + - 통합 테스트 추가 + +--- + +**작성일**: 2025-11-10 +**최종 수정일**: 2025-11-10 diff --git a/.docs/dispatch-async/08-troubleshooting.md b/.docs/dispatch-async/08-troubleshooting.md new file mode 100644 index 00000000..5778af77 --- /dev/null +++ b/.docs/dispatch-async/08-troubleshooting.md @@ -0,0 +1,606 @@ +# 트러블슈팅 가이드 + +## 📋 목차 + +1. [일반적인 문제](#일반적인-문제) +2. [큐 시스템 문제](#큐-시스템-문제) +3. [API 호출 문제](#api-호출-문제) +4. [성능 문제](#성능-문제) +5. [디버깅 팁](#디버깅-팁) + +--- + +## 일반적인 문제 + +### 문제 1: dispatch 순서가 여전히 보장되지 않음 + +#### 증상 +```javascript +dispatch(action1()); +dispatch(action2()); +dispatch(action3()); +// 실행 순서: action2 → action3 → action1 +``` + +#### 가능한 원인 + +1. **일반 dispatch와 큐 dispatch 혼용** + ```javascript + // ❌ 잘못된 사용 + dispatch(pushPanel({ name: 'PANEL_1' })); // 일반 + dispatch(pushPanelQueued({ name: 'PANEL_2' })); // 큐 + ``` + +2. **async/await 없이 비동기 처리** + ```javascript + // ❌ 잘못된 사용 + fetchData(); // Promise를 기다리지 않음 + dispatch(action()); + ``` + +3. **헬퍼 함수를 사용하지 않음** + ```javascript + // ❌ 잘못된 사용 + dispatch(asyncAction1()); + dispatch(asyncAction2()); // asyncAction1이 완료되기 전에 실행 + ``` + +#### 해결 방법 + +**방법 1: 큐 시스템 사용** (패널 액션인 경우) +```javascript +// ✅ 올바른 사용 +dispatch(enqueueMultiplePanelActions([ + pushPanelQueued({ name: 'PANEL_1' }), + pushPanelQueued({ name: 'PANEL_2' }), + pushPanelQueued({ name: 'PANEL_3' }) +])); +``` + +**방법 2: createSequentialDispatch 사용** +```javascript +// ✅ 올바른 사용 +dispatch(createSequentialDispatch([ + action1(), + action2(), + action3() +])); +``` + +**방법 3: async/await 사용** (Chrome 68+) +```javascript +// ✅ 올바른 사용 +export const myAction = () => async (dispatch, getState) => { + await dispatch(action1()); + await dispatch(action2()); + await dispatch(action3()); +}; +``` + +--- + +### 문제 2: "Cannot find module" 에러 + +#### 증상 +``` +Error: Cannot find module '../utils/dispatchHelper' +Error: Cannot find module '../middleware/panelQueueMiddleware' +``` + +#### 원인 +- 파일이 존재하지 않음 +- import 경로가 잘못됨 +- 빌드가 필요함 + +#### 해결 방법 + +**Step 1: 파일 존재 확인** +```bash +# 프로젝트 루트에서 실행 +ls -la com.twin.app.shoptime/src/utils/dispatchHelper.js +ls -la com.twin.app.shoptime/src/middleware/panelQueueMiddleware.js +ls -la com.twin.app.shoptime/src/utils/asyncActionUtils.js +``` + +**Step 2: 최신 코드 pull** +```bash +git fetch origin +git pull origin +``` + +**Step 3: node_modules 재설치** +```bash +cd com.twin.app.shoptime +rm -rf node_modules package-lock.json +npm install +``` + +**Step 4: 빌드 재실행** +```bash +npm run build +# 또는 +npm start +``` + +--- + +### 문제 3: 타입 에러 (types is not defined) + +#### 증상 +``` +ReferenceError: types is not defined +TypeError: Cannot read property 'ENQUEUE_PANEL_ACTION' of undefined +``` + +#### 원인 +actionTypes.js에 필요한 타입이 정의되지 않음 + +#### 해결 방법 + +**Step 1: actionTypes.js 확인** +```javascript +// src/actions/actionTypes.js +export const types = { + // ... 기존 타입들 ... + + // 큐 관련 타입들 (필수!) + ENQUEUE_PANEL_ACTION: 'ENQUEUE_PANEL_ACTION', + PROCESS_PANEL_QUEUE: 'PROCESS_PANEL_QUEUE', + CLEAR_PANEL_QUEUE: 'CLEAR_PANEL_QUEUE', + SET_QUEUE_PROCESSING: 'SET_QUEUE_PROCESSING', + + // 비동기 액션 타입들 (필수!) + ENQUEUE_ASYNC_PANEL_ACTION: 'ENQUEUE_ASYNC_PANEL_ACTION', + COMPLETE_ASYNC_PANEL_ACTION: 'COMPLETE_ASYNC_PANEL_ACTION', + FAIL_ASYNC_PANEL_ACTION: 'FAIL_ASYNC_PANEL_ACTION', +}; +``` + +**Step 2: import 확인** +```javascript +import { types } from '../actions/actionTypes'; +``` + +--- + +## 큐 시스템 문제 + +### 문제 4: 큐가 처리되지 않음 + +#### 증상 +```javascript +dispatch(pushPanelQueued({ name: panel_names.SEARCH_PANEL })); +// 아무 일도 일어나지 않음 +// 콘솔 로그도 없음 +``` + +#### 원인 +**panelQueueMiddleware가 등록되지 않음** (가장 흔한 문제!) + +#### 해결 방법 + +**Step 1: store.js 확인** +```javascript +// src/store/store.js +import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; + +export const store = createStore( + rootReducer, + applyMiddleware( + thunk, + panelHistoryMiddleware, + autoCloseMiddleware, + panelQueueMiddleware // ← 이것이 있는지 확인! + ) +); +``` + +**Step 2: import 경로 확인** +```javascript +// ✅ 올바른 import +import panelQueueMiddleware from '../middleware/panelQueueMiddleware'; + +// ❌ 잘못된 import +import { panelQueueMiddleware } from '../middleware/panelQueueMiddleware'; +// default export이므로 중괄호 없이 import해야 함 +``` + +**Step 3: 앱 재시작** +```bash +# 개발 서버 재시작 +npm start +``` + +**Step 4: 브라우저 캐시 삭제** +- Chrome: Ctrl+Shift+R (Windows) 또는 Cmd+Shift+R (Mac) + +--- + +### 문제 5: 큐가 무한 루프에 빠짐 + +#### 증상 +``` +[panelQueueMiddleware] 🚀 ACTION_ENQUEUED +[panelQueueMiddleware] ⚡ STARTING_QUEUE_PROCESS +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +... (무한 반복) +``` + +#### 원인 +1. 큐 처리 중에 다시 큐에 액션 추가 +2. `isProcessingQueue` 플래그가 제대로 설정되지 않음 + +#### 해결 방법 + +**방법 1: 큐 액션 내부에서 일반 dispatch 사용** +```javascript +// ❌ 잘못된 사용 (무한 루프 발생) +export const myAction = () => (dispatch) => { + dispatch(pushPanelQueued({ name: 'PANEL_1' })); + dispatch(pushPanelQueued({ name: 'PANEL_2' })); // 큐 처리 중 큐 추가 +}; + +// ✅ 올바른 사용 +export const myAction = () => (dispatch) => { + dispatch(enqueueMultiplePanelActions([ + pushPanelQueued({ name: 'PANEL_1' }), + pushPanelQueued({ name: 'PANEL_2' }) + ])); +}; +``` + +**방법 2: 리듀서 로직 확인** +```javascript +// panelReducer.js에서 확인 +case types.PROCESS_PANEL_QUEUE: { + // 이미 처리 중이면 무시 + if (state.isProcessingQueue || state.panelActionQueue.length === 0) { + return state; // ← 이 로직이 있는지 확인 + } + // ... +} +``` + +--- + +### 문제 6: 큐 통계가 업데이트되지 않음 + +#### 증상 +```javascript +store.getState().panels.queueStats +// { totalProcessed: 0, failedCount: 0, averageProcessingTime: 0 } +// 항상 0으로 유지됨 +``` + +#### 원인 +큐 처리가 정상적으로 완료되지 않음 + +#### 해결 방법 + +**Step 1: 콘솔 로그 확인** +``` +[panelReducer] ✅ QUEUE_ITEM_PROCESSED ← 이 로그가 보이는지 확인 +``` + +**Step 2: 에러 발생 확인** +```javascript +store.getState().panels.queueError +// null이어야 정상 +``` + +**Step 3: 큐 처리 완료 여부 확인** +```javascript +store.getState().panels.isProcessingQueue +// false여야 정상 (처리 완료) +``` + +--- + +## API 호출 문제 + +### 문제 7: API 성공인데 onFail이 호출됨 + +#### 증상 +```javascript +// API 호출 +// HTTP 200, retCode: 0 +// 그런데 onFail이 호출됨 +``` + +#### 원인 +프로젝트 성공 기준을 이해하지 못함 + +#### 프로젝트 성공 기준 +**HTTP 200-299 + retCode 0/'0' 둘 다 만족해야 성공!** + +```javascript +// ✅ 성공 케이스 +{ status: 200, data: { retCode: 0, data: {...} } } +{ status: 200, data: { retCode: '0', data: {...} } } + +// ❌ 실패 케이스 +{ status: 200, data: { retCode: 1, message: '에러' } } // retCode가 0이 아님 +{ status: 500, data: { retCode: 0, data: {...} } } // HTTP 에러 +``` + +#### 해결 방법 + +**방법 1: isApiSuccess 사용** +```javascript +import { isApiSuccess } from '../utils/asyncActionUtils'; + +const response = { status: 200 }; +const responseData = { retCode: 1, message: '에러' }; + +if (isApiSuccess(response, responseData)) { + // 성공 처리 +} else { + // 실패 처리 (retCode가 1이므로 실패!) +} +``` + +**방법 2: asyncActionUtils 사용** +```javascript +import { tAxiosToPromise } from '../utils/asyncActionUtils'; + +const result = await tAxiosToPromise(...); + +if (result.success) { + // HTTP 200-299 + retCode 0/'0' + console.log(result.data); +} else { + // 실패 + console.error(result.error); +} +``` + +--- + +### 문제 8: API 타임아웃이 작동하지 않음 + +#### 증상 +```javascript +dispatch(enqueueAsyncPanelAction({ + asyncAction: (d, gs, onS, onF) => { /* 느린 API */ }, + timeout: 5000 // 5초 +})); +// 10초가 지나도 타임아웃되지 않음 +``` + +#### 원인 +1. `withTimeout`이 적용되지 않음 +2. 타임아웃 값이 잘못 설정됨 + +#### 해결 방법 + +**방법 1: enqueueAsyncPanelAction 사용 시** +```javascript +// ✅ timeout 옵션 사용 +dispatch(enqueueAsyncPanelAction({ + asyncAction: (dispatch, getState, onSuccess, onFail) => { + TAxios(dispatch, getState, 'get', URL, {}, {}, onSuccess, onFail); + }, + timeout: 5000, // 5초 (ms 단위) + onFail: (error) => { + if (error.code === 'TIMEOUT') { + console.error('타임아웃 발생!'); + } + } +})); +``` + +**방법 2: withTimeout 직접 사용** +```javascript +import { withTimeout, fetchApi } from '../utils/asyncActionUtils'; + +const result = await withTimeout( + fetchApi('/api/slow-endpoint'), + 5000, // 5초 + '요청 시간이 초과되었습니다' +); + +if (result.error?.code === 'TIMEOUT') { + console.error('타임아웃!'); +} +``` + +--- + +## 성능 문제 + +### 문제 9: 큐 처리가 너무 느림 + +#### 증상 +```javascript +// 100개의 패널 액션을 큐에 추가 +// 처리하는데 10초 이상 소요 +``` + +#### 원인 +1. 각 액션이 복잡한 로직 수행 +2. 동기적으로 처리되어 병목 발생 + +#### 해결 방법 + +**방법 1: 불필요한 액션 제거** +```javascript +// ❌ 잘못된 사용 +for (let i = 0; i < 100; i++) { + dispatch(pushPanelQueued({ name: `PANEL_${i}` })); +} + +// ✅ 올바른 사용 - 필요한 것만 +dispatch(pushPanelQueued({ name: 'MAIN_PANEL' })); +``` + +**방법 2: 배치 처리** +```javascript +// 한 번에 여러 액션 추가 +dispatch(enqueueMultiplePanelActions( + panels.map(panel => pushPanelQueued(panel)) +)); +``` + +**방법 3: 병렬 처리가 필요하면 큐 사용 안함** +```javascript +// 순서가 중요하지 않은 경우 +dispatch(createParallelDispatch([ + fetchData1(), + fetchData2(), + fetchData3() +])); +``` + +--- + +### 문제 10: 메모리 누수 + +#### 증상 +```javascript +// 오랜 시간 앱 사용 후 +store.getState().panels.completedAsyncActions.length +// → 10000개 이상 +``` + +#### 원인 +완료된 비동기 액션 ID가 계속 누적됨 + +#### 해결 방법 + +**방법 1: 주기적으로 클리어** +```javascript +// 일정 시간마다 완료된 액션 정리 +setInterval(() => { + const state = store.getState().panels; + + if (state.completedAsyncActions.length > 1000) { + // 클리어 액션 dispatch + dispatch({ type: types.CLEAR_COMPLETED_ASYNC_ACTIONS }); + } +}, 60000); // 1분마다 +``` + +**방법 2: 리듀서에 최대 개수 제한 추가** +```javascript +// panelReducer.js +case types.COMPLETE_ASYNC_PANEL_ACTION: { + const newCompleted = [...state.completedAsyncActions, action.payload.actionId]; + + // 최근 100개만 유지 + const trimmed = newCompleted.slice(-100); + + return { + ...state, + completedAsyncActions: trimmed + }; +} +``` + +--- + +## 디버깅 팁 + +### Tip 1: 콘솔 로그 활용 + +모든 헬퍼 함수와 미들웨어는 상세한 로그를 출력합니다: + +```javascript +// 큐 관련 로그 +[panelQueueMiddleware] 🚀 ACTION_ENQUEUED +[panelQueueMiddleware] ⚡ STARTING_QUEUE_PROCESS +[panelReducer] 🟡 PROCESS_PANEL_QUEUE +[panelReducer] 🟡 PROCESSING_QUEUE_ITEM +[panelReducer] ✅ QUEUE_ITEM_PROCESSED + +// 비동기 액션 로그 +[queuedPanelActions] 🔄 ENQUEUE_ASYNC_PANEL_ACTION +[queuedPanelActions] ⚡ EXECUTING_ASYNC_ACTION +[queuedPanelActions] ✅ ASYNC_ACTION_SUCCESS + +// asyncActionUtils 로그 +[asyncActionUtils] 🌐 FETCH_API_START +[asyncActionUtils] 📊 API_RESPONSE +[asyncActionUtils] ✅ TAXIOS_SUCCESS +``` + +### Tip 2: Redux DevTools 사용 + +1. Chrome 확장 프로그램 설치: Redux DevTools +2. 개발자 도구 → Redux 탭 +3. 액션 히스토리 확인 +4. State diff 확인 + +### Tip 3: 브레이크포인트 설정 + +```javascript +// 디버깅용 브레이크포인트 +export const myAction = () => (dispatch, getState) => { + debugger; // ← 여기서 멈춤 + + const state = getState(); + console.log('Current state:', state); + + dispatch(action1()); + + debugger; // ← 여기서 다시 멈춤 +}; +``` + +### Tip 4: State 스냅샷 + +```javascript +// 콘솔에서 실행 +const snapshot = JSON.parse(JSON.stringify(store.getState())); +console.log(snapshot); + +// 특정 부분만 +const panelsSnapshot = JSON.parse(JSON.stringify(store.getState().panels)); +console.log(panelsSnapshot); +``` + +### Tip 5: 큐 상태 모니터링 + +```javascript +// 콘솔에서 실행 +window.monitorQueue = setInterval(() => { + const state = store.getState().panels; + console.log('Queue status:', { + queueLength: state.panelActionQueue.length, + isProcessing: state.isProcessingQueue, + stats: state.queueStats + }); +}, 1000); + +// 중지 +clearInterval(window.monitorQueue); +``` + +--- + +## 도움이 필요하신가요? + +### 체크리스트 + +문제 해결 전에 다음을 확인하세요: + +- [ ] panelQueueMiddleware가 store.js에 등록되어 있는가? +- [ ] 필요한 파일들이 모두 존재하는가? +- [ ] actionTypes.js에 필요한 타입들이 정의되어 있는가? +- [ ] 콘솔 로그를 확인했는가? +- [ ] Redux DevTools로 액션 흐름을 확인했는가? +- [ ] 앱을 재시작했는가? +- [ ] 브라우저 캐시를 삭제했는가? + +### 추가 리소스 + +- [README.md](./README.md) - 전체 개요 +- [06-setup-guide.md](./06-setup-guide.md) - 설정 가이드 +- [05-usage-patterns.md](./05-usage-patterns.md) - 사용 패턴 +- [07-changelog.md](./07-changelog.md) - 변경 이력 + +--- + +**작성일**: 2025-11-10 +**최종 수정일**: 2025-11-10 diff --git a/.docs/dispatch-async/README.md b/.docs/dispatch-async/README.md index f5aba523..21572afc 100644 --- a/.docs/dispatch-async/README.md +++ b/.docs/dispatch-async/README.md @@ -7,6 +7,9 @@ 3. [해결 방법 2: asyncActionUtils.js](./03-solution-async-utils.md) 4. [해결 방법 3: 큐 기반 패널 액션 시스템](./04-solution-queue-system.md) 5. [사용 패턴 및 예제](./05-usage-patterns.md) +6. [설정 가이드](./06-setup-guide.md) ⭐ +7. [변경 이력 (Changelog)](./07-changelog.md) +8. [트러블슈팅](./08-troubleshooting.md) ⭐ ## 🎯 개요 @@ -114,11 +117,19 @@ f9290a1 [251106] fix: Dispatch Queue implementation 각 솔루션에 대한 자세한 설명은 개별 문서를 참고하세요. +### 시작하기 +- **처음 시작한다면** → [06-setup-guide.md](./06-setup-guide.md) ⭐ +- **문제가 발생했다면** → [08-troubleshooting.md](./08-troubleshooting.md) ⭐ + +### 이해하기 - 기존 코드의 문제점이 궁금하다면 → [01-problem.md](./01-problem.md) - dispatchHelper 사용법이 궁금하다면 → [02-solution-dispatch-helper.md](./02-solution-dispatch-helper.md) - asyncActionUtils 사용법이 궁금하다면 → [03-solution-async-utils.md](./03-solution-async-utils.md) - 큐 시스템 사용법이 궁금하다면 → [04-solution-queue-system.md](./04-solution-queue-system.md) + +### 실전 적용 - 실제 사용 예제가 궁금하다면 → [05-usage-patterns.md](./05-usage-patterns.md) +- 변경 이력을 확인하려면 → [07-changelog.md](./07-changelog.md) ---