Skip to content

Commit 016b892

Browse files
committed
feat: align simulator outputs and update visualization/docs
1 parent 48809cc commit 016b892

86 files changed

Lines changed: 7466 additions & 84 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
3. **End-to-End**: Track data flow completely before answering
1616
4. **Goal-Focused**: Ask what user is trying to solve first
1717
5. **Diagnose**: Analyze before proposing solutions
18+
6. **Hot Reload First**: 프론트 UI/스타일 수정 중에는 `pnpm build`를 자동 실행하지 말고, 사용자가 명시적으로 요청할 때만 빌드 실행
19+
7. **Bug Claims Need Proof**: 버그 제보/반박 시 즉시 수정하지 말고 재현, 코드 근거, 영향 범위를 먼저 확인한 뒤 변경할 것
1820

1921
## 🏗️ Structure
2022
```

MEMORY.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,25 @@
1313
## Operational Preferences
1414
- 작업 전에 현재 코드/문서 실측 후 판단하기.
1515
- 계획 문서보다 실제 코드 상태(`app.ts`, 서비스 엔트리, git status)를 우선 신뢰하기.
16+
17+
## 2026-03-05 - JS Viewer Fix Record
18+
- 사용자 이슈: "중국어가 안 보이고, Playground 버튼/JS 뷰어 탭이 안 보임".
19+
- 원인:
20+
- 현재 작업 브랜치에 `zh` 로케일 파일/리소스 연결이 누락됨.
21+
- `PlaygroundPage`가 JS를 시각화 렌더 조건에서 제외하고 있어 JS 관련 탭이 표시되지 않음.
22+
- 수정:
23+
- `packages/frontend/src/i18n.ts``zh` 리소스 복구.
24+
- `packages/frontend/src/locales/zh/translation.json` 복구.
25+
- `packages/frontend/src/components/LanguageSelector.tsx`를 3개 언어(`en/ko/zh`) 선택 구조로 복구.
26+
- `packages/frontend/src/features/playground/PlaygroundPage.tsx`를 JS 탭 로직 포함 버전으로 복구 (`showJsMemoryTab`, `canRenderVisualizer`에 JS 포함).
27+
- 검증:
28+
- `pnpm --filter @codeinsight/frontend build` 성공.
29+
- 실행 중 dev 서버(`127.0.0.1:5174`)에서 소스 응답 확인:
30+
- `i18n.ts``zhTranslation` 로딩 확인.
31+
- `LanguageSelector.tsx``中文`/`grid-cols-3` 확인.
32+
- `PlaygroundPage.tsx``jsMemory`/`showJsMemoryTab` 확인.
33+
- `StepControls.tsx``playground-run-button` 존재 확인.
34+
35+
## 2026-03-05 - Frontend Workflow Preference
36+
- 사용자 명시 선호: 프론트 UI/스타일 작업은 핫리로드로 확인.
37+
- 기본 원칙: 사용자가 요청하지 않으면 `pnpm build` 자동 실행하지 않음.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# Viz Tab Data-Driven Visibility Plan
2+
Date: 2026-03-05
3+
4+
## 목표
5+
6+
LessonUnifiedView의 시각화 탭(Flow / Memory / JS Memory)을
7+
언어 하드코딩이 아닌 **실제 데이터 유무**로 노출 여부를 결정한다.
8+
9+
---
10+
11+
## 현황 및 문제점
12+
13+
```ts
14+
// LessonUnifiedView.tsx:78-80 (현재)
15+
const showMemoryTab = languageId === 'c' || languageId === 'cpp'; // 언어만 봄
16+
const showJsMemoryTab = languageId === 'javascript'; // 언어만 봄
17+
```
18+
19+
- C/C++ 레슨이라도 메모리 데이터가 없으면 Memory 탭이 떠서 텅 빔
20+
- JS 레슨이라도 eventLoop/scope만 있는 레슨(js-1-3 등)에 JS Memory 탭이 불필요하게 노출됨
21+
- 탭이 1개뿐일 때도 탭 바 UI가 표시됨
22+
23+
---
24+
25+
## 데이터 구조 확인 결과
26+
27+
### JS 레슨 필드 분류
28+
29+
| 필드 위치 | 레슨 유형 | 예시 |
30+
|-----------|-----------|------|
31+
| `step.eventLoopState` | event loop (js-1-x, js-4-3 등) | js-1-3 |
32+
| `step.scopeState` | 스코프 체인 (js-2-x 등) | js-2-1 |
33+
| `step.promiseState` | Promise (js-4-x 등) | js-4-1 |
34+
| `step.thisState` | this 바인딩 | js-3-x |
35+
| `step.prototypeState` | 프로토타입 체인 | js-3-x |
36+
| `step.memoryState` (nested stack/heap) | 참조값/객체 레슨 | js-5-x, js-7-x, js-9-x |
37+
38+
**JS Memory 탭 필요**: `step.memoryState`가 있는 레슨만 (js-5-x, js-7-1, js-7-3, js-9-1, js-9-2)
39+
**Flow 탭만 필요**: 나머지 (eventLoopState/scopeState 등만 있는 레슨)
40+
41+
### C/C++ 레슨 필드
42+
43+
- `step.stack`: top-level 배열 (메모리 스택 프레임)
44+
- `step.heap`: top-level 배열 (힙 변수)
45+
- `step.memoryChanges`: 변경 추적 (있을 수 있음)
46+
47+
---
48+
49+
## 변경 범위
50+
51+
**파일 2개만 수정**
52+
53+
1. `packages/frontend/src/features/courses/utils/visualizationData.ts`
54+
2. `packages/frontend/src/features/courses/components/LessonUnifiedView.tsx`
55+
56+
---
57+
58+
## 구현 명세
59+
60+
### Step 1: visualizationData.ts에 함수 추가
61+
62+
```ts
63+
/**
64+
* C/C++ Memory 탭 노출 여부 판단
65+
* - step.stack (top-level 배열, 비어있지 않음)
66+
* - step.heap (top-level 배열)
67+
* - step.memoryChanges
68+
*/
69+
export function hasClassicMemoryData(steps: LessonStep[]): boolean {
70+
return steps.some(step => {
71+
const s = step as Record<string, unknown>;
72+
return (
73+
(Array.isArray(s.stack) && (s.stack as unknown[]).length > 0) ||
74+
(Array.isArray(s.heap) && (s.heap as unknown[]).length > 0) ||
75+
hasMeaningfulValue(s.memoryChanges)
76+
);
77+
});
78+
}
79+
80+
/**
81+
* JS Memory 탭 노출 여부 판단
82+
* - step.memoryState (nested {stack, heap}) 가 있으면 참조 그래프 탭 필요
83+
* - eventLoopState/scopeState 등만 있으면 false
84+
*/
85+
export function hasJsMemoryData(steps: LessonStep[]): boolean {
86+
return steps.some(step => {
87+
const s = step as Record<string, unknown>;
88+
return hasMeaningfulValue(s.memoryState);
89+
});
90+
}
91+
```
92+
93+
### Step 2: LessonUnifiedView.tsx 수정
94+
95+
```ts
96+
// 추가 import
97+
import { hasMeaningfulValue, hasClassicMemoryData, hasJsMemoryData } from '../utils/visualizationData';
98+
99+
// 기존 (78-80줄)
100+
const showMemoryTab = languageId === 'c' || languageId === 'cpp';
101+
const showJsMemoryTab = languageId === 'javascript';
102+
103+
// 변경 후 — useMemo로 감싸서 불필요한 재계산 방지
104+
// (nav.vizStepIndices는 useRoundNavigation 내부에서 이미 useMemo로 안정적)
105+
const showMemoryTab = useMemo(
106+
() => (languageId === 'c' || languageId === 'cpp')
107+
&& hasClassicMemoryData(nav.vizStepIndices.map(i => steps[i])),
108+
[languageId, nav.vizStepIndices, steps]
109+
);
110+
const showJsMemoryTab = useMemo(
111+
() => languageId === 'javascript'
112+
&& hasJsMemoryData(nav.vizStepIndices.map(i => steps[i])),
113+
[languageId, nav.vizStepIndices, steps]
114+
);
115+
```
116+
117+
기존 `useEffect` fallback (130-137줄)은 그대로 유지:
118+
```ts
119+
useEffect(() => {
120+
if (activeVizTab === 'memory' && !showMemoryTab) setActiveVizTab('flow');
121+
if (activeVizTab === 'jsMemory' && !showJsMemoryTab) setActiveVizTab('flow');
122+
}, [activeVizTab, showMemoryTab, showJsMemoryTab]);
123+
```
124+
125+
---
126+
127+
## 검증 케이스
128+
129+
| 레슨 | 데이터 | 예상 탭 |
130+
|------|--------|---------|
131+
| js-1-3 | eventLoopState만 | Flow 탭만 (탭 바 숨김) |
132+
| js-1-1~1-4, js-4-3 | eventLoopState만 | Flow 탭만 (탭 바 숨김) |
133+
| js-5-1~5-3 | memoryState(stack/heap) | Flow + JS Memory |
134+
| js-7-1, js-7-3, js-9-1, js-9-2 | memoryState(stack/heap) | Flow + JS Memory |
135+
| C 메모리 레슨 | step.stack/heap 있음 | Flow + Memory |
136+
| C 순수 flow 레슨 | step.stack 비어있거나 없음 | Flow 탭만 (탭 바 숨김) |
137+
| C++ 메모리 레슨 | step.stack/heap 있음 | Flow + Memory |
138+
| C 개념 전용 레슨 (전처리기 등) | 모든 viz 스텝 stack/heap 비어있음 | Flow 탭만 (**현재보다 개선**) |
139+
| js-7-2 | memoryState.heap만 있음 (stack 없음) | Flow + JS Memory |
140+
141+
---
142+
143+
## 코드베이스 정밀검사 결과 (2026-03-05)
144+
145+
검사 범위: `useLessonVisualization.ts`, `useRoundNavigation.ts`, 전체 lesson JSON
146+
147+
| 항목 | 결과 |
148+
|------|------|
149+
| `memoryChanges` 필드 존재 여부 | `useLessonVisualization:407`에 분기 존재. 현재 JSON에는 없으나 미래 대비 유지 |
150+
| JS 레슨 top-level `stack` 사용 여부 | 없음. 전부 `step.memoryState.stack` (nested) |
151+
| C/C++ `memoryState` nested 사용 여부 | 없음. 전부 top-level `step.stack`/`step.heap` |
152+
| js-7-2 데이터 구조 | `memoryState.heap` 만 있음. `hasMeaningfulValue(memoryState)` → true ✓ |
153+
| C 개념 전용 레슨 (빈 stack/heap) | Memory 탭 숨김 — 현재보다 나은 동작 |
154+
| Delta format 영향 | 백엔드 seed 시 확장 완료 → 프론트엔드는 항상 완전한 스텝 수신 |
155+
| Carry-forward 영향 | `useLessonVisualization` 내부에서만 동작 → 판별 함수에 무관 |
156+
| `nav.vizStepIndices` 안정성 | `useRoundNavigation``useMemo([steps])` → 안정적 |
157+
| 성능 | `useMemo` 추가로 스텝 이동마다 불필요한 재계산 제거 |
158+
159+
---
160+
161+
## 완료 기준
162+
163+
- [ ] `hasClassicMemoryData`, `hasJsMemoryData` 함수 추가
164+
- [ ] LessonUnifiedView `showMemoryTab`, `showJsMemoryTab` 데이터 기반으로 교체
165+
- [ ] js-1-3 접속 시 탭 바 없음 확인
166+
- [ ] js-5-1 접속 시 Flow + JS Memory 탭 확인
167+
- [ ] C 메모리 레슨 접속 시 Flow + Memory 탭 확인
168+
- [ ] activeVizTab fallback 정상 동작 확인 (탭 사라질 때 flow로 복귀)

0 commit comments

Comments
 (0)