create-ax-project 1.0.0 β†’ 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/package.json +1 -1
  2. package/template/.claude/CLAUDE.md +0 -7
  3. package/template/.claude/commands/CLAUDE.md +0 -0
  4. package/template/.claude/hooks/CLAUDE.md +0 -0
  5. package/template/.claude/skills/ai-collaboration/CLAUDE.md +0 -0
  6. package/template/.claude/skills/auto-checkpoint/CLAUDE.md +0 -0
  7. package/template/.claude/skills/context-compression/CLAUDE.md +0 -0
  8. package/template/.claude/skills/context-compression/prompts/CLAUDE.md +0 -0
  9. package/template/.claude/skills/output-validator/CLAUDE.md +0 -0
  10. package/template/.claude/skills/smart-handoff/CLAUDE.md +0 -0
  11. package/template/.claude/skills/stage-transition/CLAUDE.md +0 -0
  12. package/template/.claude/skills/stage-transition/prompts/CLAUDE.md +0 -0
  13. package/template/config/CLAUDE.md +0 -0
  14. package/template/scripts/CLAUDE.md +0 -0
  15. package/template/stages/01-brainstorm/HANDOFF.md +0 -110
  16. package/template/stages/01-brainstorm/inputs/CLAUDE.md +0 -0
  17. package/template/stages/01-brainstorm/inputs/project_brief.md +0 -40
  18. package/template/stages/01-brainstorm/outputs/CLAUDE.md +0 -0
  19. package/template/stages/01-brainstorm/outputs/ideas.md +0 -159
  20. package/template/stages/01-brainstorm/outputs/requirements_analysis.md +0 -222
  21. package/template/stages/01-brainstorm/prompts/CLAUDE.md +0 -0
  22. package/template/stages/01-brainstorm/templates/CLAUDE.md +0 -0
  23. package/template/stages/02-research/HANDOFF.md +0 -158
  24. package/template/stages/02-research/outputs/CLAUDE.md +0 -0
  25. package/template/stages/02-research/outputs/feasibility_report.md +0 -176
  26. package/template/stages/02-research/outputs/tech_research.md +0 -403
  27. package/template/stages/02-research/prompts/CLAUDE.md +0 -0
  28. package/template/stages/03-planning/HANDOFF.md +0 -168
  29. package/template/stages/03-planning/outputs/CLAUDE.md +0 -0
  30. package/template/stages/03-planning/outputs/architecture.md +0 -400
  31. package/template/stages/03-planning/outputs/implementation.yaml +0 -209
  32. package/template/stages/03-planning/outputs/project_plan.md +0 -204
  33. package/template/stages/03-planning/outputs/tech_stack.md +0 -176
  34. package/template/stages/03-planning/prompts/CLAUDE.md +0 -0
  35. package/template/stages/04-ui-ux/HANDOFF.md +0 -165
  36. package/template/stages/04-ui-ux/outputs/CLAUDE.md +0 -0
  37. package/template/stages/04-ui-ux/outputs/design_system.md +0 -449
  38. package/template/stages/04-ui-ux/outputs/user_flows.md +0 -321
  39. package/template/stages/04-ui-ux/outputs/wireframes.md +0 -241
  40. package/template/stages/04-ui-ux/prompts/CLAUDE.md +0 -0
  41. package/template/stages/05-task-management/HANDOFF.md +0 -187
  42. package/template/stages/05-task-management/outputs/CLAUDE.md +0 -0
  43. package/template/stages/05-task-management/outputs/milestones.md +0 -253
  44. package/template/stages/05-task-management/outputs/sprint_plan.md +0 -203
  45. package/template/stages/05-task-management/outputs/tasks.md +0 -402
  46. package/template/stages/05-task-management/prompts/CLAUDE.md +0 -0
  47. package/template/stages/05-task-management/templates/CLAUDE.md +0 -0
  48. package/template/stages/06-implementation/HANDOFF.md +0 -184
  49. package/template/stages/06-implementation/prompts/CLAUDE.md +0 -0
  50. package/template/stages/07-refactoring/HANDOFF.md +0 -82
  51. package/template/stages/07-refactoring/outputs/refactoring_report.md +0 -102
  52. package/template/stages/07-refactoring/prompts/CLAUDE.md +0 -0
  53. package/template/stages/08-qa/HANDOFF.md +0 -114
  54. package/template/stages/08-qa/outputs/qa_report.md +0 -138
  55. package/template/stages/08-qa/prompts/CLAUDE.md +0 -0
  56. package/template/stages/09-testing/HANDOFF.md +0 -118
  57. package/template/stages/09-testing/outputs/test_report.md +0 -146
  58. package/template/stages/09-testing/prompts/CLAUDE.md +0 -0
  59. package/template/stages/10-deployment/HANDOFF.md +0 -141
  60. package/template/stages/10-deployment/prompts/CLAUDE.md +0 -0
  61. package/template/stages/10-deployment/templates/CLAUDE.md +0 -0
  62. package/template/state/templates/CLAUDE.md +0 -0
@@ -1,400 +0,0 @@
1
- # πŸ—οΈ Snake Game μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜ μ„€κ³„μ„œ
2
-
3
- > 생성일: 2026-01-21
4
- > μŠ€ν…Œμ΄μ§€: 03-planning
5
- > ν”„λ‘œμ νŠΈ: snake-game
6
- > AI 도ꡬ: Gemini CLI
7
-
8
- ---
9
-
10
- ## 1. μ»΄ν¬λ„ŒνŠΈ ꡬ쑰
11
-
12
- 이 ν”„λ‘œμ νŠΈλŠ” 단일 μΊ”λ²„μŠ€ λ Œλ”λ§ 방식과 React UI μ˜€λ²„λ ˆμ΄λ₯Ό κ²°ν•©ν•œ **ν•˜μ΄λΈŒλ¦¬λ“œ ꡬ쑰**λ₯Ό μ±„νƒν•©λ‹ˆλ‹€.
13
-
14
- ### 1.1 μ»΄ν¬λ„ŒνŠΈ μ—­ν• 
15
-
16
- | μ»΄ν¬λ„ŒνŠΈ | νƒ€μž… | μ—­ν•  |
17
- |---------|------|------|
18
- | **App** | Container | 전체 λ ˆμ΄μ•„μ›ƒ, μ΅œμƒμœ„ μƒνƒœ(ν…Œλ§ˆ λ“±) 관리 |
19
- | **GameEngine** | Smart | 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ—°κ²°, Canvas/UI 쑰율 |
20
- | **CanvasLayer** | Presentation | Canvas μ ‘κ·Ό, κ²Œμž„ λ Œλ”λ§ μˆ˜ν–‰ |
21
- | **UIOverlay** | Presentation | HTML/CSS 기반 UI (점수, λͺ¨λ‹¬ λ“±) |
22
- | **ScoreBoard** | UI | ν˜„μž¬ μ μˆ˜μ™€ 졜고 점수 ν‘œμ‹œ |
23
- | **GameOverModal** | UI | κ²Œμž„ μ’…λ£Œ μ‹œ μž¬μ‹œμž‘ λ²„νŠΌκ³Ό κ²°κ³Ό |
24
- | **StartScreen** | UI | κ²Œμž„ μ‹œμž‘ μ „ 타이틀 ν™”λ©΄ |
25
- | **MobileControls** | UI | λͺ¨λ°”일 λ°©ν–₯ λ²„νŠΌ |
26
-
27
- ### 1.2 계측 ꡬ쑰 λ‹€μ΄μ–΄κ·Έλž¨
28
-
29
- ```
30
- +-------------------------------------------------------+
31
- | App |
32
- |-------------------------------------------------------|
33
- | +-------------------------------------------------+ |
34
- | | GameEngine | |
35
- | | (Holds Game State, Refs, and Event Listeners) | |
36
- | |-------------------------------------------------| |
37
- | | +-------------------+ +-------------------+ | |
38
- | | | CanvasLayer | | UIOverlay | | |
39
- | | | (Rendering Target)| | (React Components)| | |
40
- | | | | | | | |
41
- | | | [Snake] [Food] | | [ScoreBoard] | | |
42
- | | | [Grid] [Fx] | | [GameOverModal] | | |
43
- | | | | | [MobileControls] | | |
44
- | | +-------------------+ +-------------------+ | |
45
- | +-------------------------------------------------+ |
46
- +-------------------------------------------------------+
47
- ```
48
-
49
- ### 1.3 μ»΄ν¬λ„ŒνŠΈ μ˜μ‘΄μ„± κ·Έλž˜ν”„
50
-
51
- ```
52
- App
53
- β”‚
54
- GameEngine
55
- β”‚
56
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
57
- β”‚ β”‚ β”‚
58
- CanvasLayer UIOverlay Hooks
59
- β”‚ β”‚ β”‚
60
- β”‚ β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β” β”‚
61
- β”‚ β”‚ β”‚ β”‚ β”‚
62
- β”‚ Score Modal Mobile β”‚
63
- β”‚ Board Over Controlsβ”‚
64
- β”‚ β”‚
65
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
66
- Canvas Context
67
- ```
68
-
69
- ---
70
-
71
- ## 2. 데이터 흐름
72
-
73
- React의 선언적 μƒνƒœ 관리와 Canvas의 λͺ…λ Ήν˜• λ Œλ”λ§μ„ μ‘°ν™”μ‹œν‚€λŠ” 것이 ν•΅μ‹¬μž…λ‹ˆλ‹€.
74
-
75
- ### 2.1 κ²Œμž„ μƒνƒœ 흐름
76
-
77
- ```
78
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
79
- β”‚ State Flow β”‚
80
- β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
81
- β”‚ β”‚
82
- β”‚ useReducer ──────────────────────────────────────┐ β”‚
83
- β”‚ β”‚ β”‚ β”‚
84
- β”‚ β–Ό β”‚ β”‚
85
- β”‚ gameState ────────────────────────────────────► β”‚ β”‚
86
- β”‚ (snake, food, direction, score, status) β”‚ β”‚
87
- β”‚ β”‚ β”‚ β”‚
88
- β”‚ β”‚ requestAnimationFrame β”‚ β”‚
89
- β”‚ β–Ό β”‚ β”‚ β”‚
90
- β”‚ gameLoop β—„β”€β”€β”€β”€β”˜ β”‚ β”‚
91
- β”‚ β”‚ β”‚ β”‚
92
- β”‚ β”œβ”€β”€β–Ί dispatch({ type: 'TICK' }) β”‚ β”‚
93
- β”‚ β”‚ β”‚ β”‚
94
- β”‚ β–Ό β”‚ β”‚
95
- β”‚ Canvas.draw() β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
96
- β”‚ β”‚
97
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
98
- ```
99
-
100
- ### 2.2 이벀트 처리 흐름
101
-
102
- ```
103
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
104
- β”‚ Event Flow β”‚
105
- β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
106
- β”‚ β”‚
107
- β”‚ User Input β”‚
108
- β”‚ β”‚ β”‚
109
- β”‚ β”œβ”€β”€β–Ί Keyboard (useKeyboard) ──┐ β”‚
110
- β”‚ β”‚ β”‚ β”‚
111
- β”‚ └──► Touch (useSwipe) ───────── β”‚
112
- β”‚ β”‚ β”‚
113
- β”‚ β–Ό β”‚
114
- β”‚ Direction Normalized β”‚
115
- β”‚ (UP/DOWN/LEFT/RIGHT) β”‚
116
- β”‚ β”‚ β”‚
117
- β”‚ β–Ό β”‚
118
- β”‚ dispatch({ type: 'CHANGE_DIRECTION' }) β”‚
119
- β”‚ β”‚ β”‚
120
- β”‚ β–Ό β”‚
121
- β”‚ Collision Check β”‚
122
- β”‚ β”‚ β”‚
123
- β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
124
- β”‚ β”‚ β”‚ β”‚ β”‚
125
- β”‚ β–Ό β–Ό β–Ό β”‚
126
- β”‚ Wall Hit Self Hit Eat Food β”‚
127
- β”‚ β”‚ β”‚ β”‚ β”‚
128
- β”‚ β–Ό β–Ό β–Ό β”‚
129
- β”‚ GAME_OVER GAME_OVER Grow +10 β”‚
130
- β”‚ β”‚
131
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
132
- ```
133
-
134
- ### 2.3 μƒνƒœ vs μ°Έμ‘° 뢄리
135
-
136
- | 데이터 | 관리 방식 | 이유 |
137
- |--------|----------|------|
138
- | snake, food, score | `useReducer` | UI λ¦¬λ Œλ”λ§ ν•„μš” |
139
- | direction (버퍼) | `useRef` | λΉ λ₯Έ μž…λ ₯ 처리, λ¦¬λ Œλ”λ§ λ°©μ§€ |
140
- | canvasRef | `useRef` | DOM μ°Έμ‘° |
141
- | animationFrameId | `useRef` | 루프 관리 |
142
-
143
- ---
144
-
145
- ## 3. μ»€μŠ€ν…€ ν›… 섀계
146
-
147
- ### 3.1 useGameLoop
148
-
149
- ```typescript
150
- /**
151
- * requestAnimationFrame 기반 κ²Œμž„ 루프 관리
152
- * @param callback λ§€ ν”„λ ˆμž„ 싀행될 ν•¨μˆ˜
153
- * @param isRunning 루프 μ‹€ν–‰ μ—¬λΆ€
154
- */
155
- const useGameLoop = (
156
- callback: (deltaTime: number) => void,
157
- isRunning: boolean
158
- ) => void;
159
- ```
160
-
161
- **νŠΉμ§•**:
162
- - μ»΄ν¬λ„ŒνŠΈ μ–Έλ§ˆμš΄νŠΈ μ‹œ μžλ™ 정리
163
- - deltaTime κ³„μ‚°ν•˜μ—¬ ν”„λ ˆμž„ 독립적 μ• λ‹ˆλ©”μ΄μ…˜
164
- - isRunning으둜 μΌμ‹œμ •μ§€/재개 μ œμ–΄
165
-
166
- ### 3.2 useKeyboard
167
-
168
- ```typescript
169
- /**
170
- * ν‚€λ³΄λ“œ μž…λ ₯ 감지 및 λ°©ν–₯ λ³€ν™˜
171
- * @param onDirectionChange λ°©ν–₯ λ³€κ²½ μ‹œ 콜백
172
- * @param onPause μΌμ‹œμ •μ§€ ν† κΈ€ 콜백
173
- * @param onRestart μž¬μ‹œμž‘ 콜백
174
- */
175
- const useKeyboard = (
176
- onDirectionChange: (direction: Direction) => void,
177
- onPause?: () => void,
178
- onRestart?: () => void
179
- ) => void;
180
- ```
181
-
182
- **지원 ν‚€**:
183
- - Arrow Keys: λ°©ν–₯ 이동
184
- - WASD: λ°©ν–₯ 이동 (λŒ€μ•ˆ)
185
- - P / Escape: μΌμ‹œμ •μ§€
186
- - R / Space: μž¬μ‹œμž‘
187
-
188
- ### 3.3 useSwipe
189
-
190
- ```typescript
191
- /**
192
- * ν„°μΉ˜ μŠ€μ™€μ΄ν”„ 제슀처 감지
193
- * @param handlers 각 λ°©ν–₯별 ν•Έλ“€λŸ¬
194
- */
195
- const useSwipe = (handlers: {
196
- left?: () => void;
197
- right?: () => void;
198
- up?: () => void;
199
- down?: () => void;
200
- }) => void;
201
- ```
202
-
203
- **νŠΉμ§•**:
204
- - μ΅œμ†Œ μŠ€μ™€μ΄ν”„ 거리 (threshold): 50px
205
- - μ΅œλŒ€ μŠ€μ™€μ΄ν”„ μ‹œκ°„: 500ms
206
- - passive λ¦¬μŠ€λ„ˆλ‘œ μ„±λŠ₯ μ΅œμ ν™”
207
-
208
- ### 3.4 useHighScore
209
-
210
- ```typescript
211
- /**
212
- * localStorage 기반 졜고 점수 관리
213
- */
214
- const useHighScore = () => {
215
- highScore: number;
216
- updateHighScore: (score: number) => boolean; // κ°±μ‹  μ—¬λΆ€ λ°˜ν™˜
217
- resetHighScore: () => void;
218
- };
219
- ```
220
-
221
- ---
222
-
223
- ## 4. 파일/폴더 ꡬ쑰
224
-
225
- ```
226
- snake-game/
227
- β”œβ”€β”€ public/
228
- β”‚ └── favicon.svg
229
- β”œβ”€β”€ src/
230
- β”‚ β”œβ”€β”€ assets/ # 정적 μžμ‚°
231
- β”‚ β”‚ └── sounds/ # 효과음 (선택)
232
- β”‚ β”‚
233
- β”‚ β”œβ”€β”€ components/ # React UI μ»΄ν¬λ„ŒνŠΈ
234
- β”‚ β”‚ β”œβ”€β”€ CanvasLayer.tsx # Canvas 래퍼
235
- β”‚ β”‚ β”œβ”€β”€ GameOverlay.tsx # UI μ˜€λ²„λ ˆμ΄ μ»¨ν…Œμ΄λ„ˆ
236
- β”‚ β”‚ β”œβ”€β”€ ScoreBoard.tsx # 점수판
237
- β”‚ β”‚ β”œβ”€β”€ StartScreen.tsx # μ‹œμž‘ ν™”λ©΄
238
- β”‚ β”‚ β”œβ”€β”€ GameOverModal.tsx # κ²Œμž„ μ˜€λ²„ λͺ¨λ‹¬
239
- β”‚ β”‚ └── MobileControls.tsx # λͺ¨λ°”일 λ²„νŠΌ
240
- β”‚ β”‚
241
- β”‚ β”œβ”€β”€ hooks/ # μ»€μŠ€ν…€ ν›…
242
- β”‚ β”‚ β”œβ”€β”€ useGameLoop.ts
243
- β”‚ β”‚ β”œβ”€β”€ useKeyboard.ts
244
- β”‚ β”‚ β”œβ”€β”€ useSwipe.ts
245
- β”‚ β”‚ └── useHighScore.ts
246
- β”‚ β”‚
247
- β”‚ β”œβ”€β”€ engine/ # κ²Œμž„ 핡심 둜직
248
- β”‚ β”‚ β”œβ”€β”€ gameReducer.ts # μƒνƒœ 관리 λ¦¬λ“€μ„œ
249
- β”‚ β”‚ β”œβ”€β”€ collision.ts # 좩돌 감지
250
- β”‚ β”‚ └── renderer.ts # Canvas λ Œλ”λ§
251
- β”‚ β”‚
252
- β”‚ β”œβ”€β”€ types/ # TypeScript νƒ€μž…
253
- β”‚ β”‚ └── index.ts
254
- β”‚ β”‚
255
- β”‚ β”œβ”€β”€ utils/ # μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
256
- β”‚ β”‚ └── random.ts # 랜덀 μ’Œν‘œ 생성
257
- β”‚ β”‚
258
- β”‚ β”œβ”€β”€ constants/ # μƒμˆ˜ μ •μ˜
259
- β”‚ β”‚ └── config.ts
260
- β”‚ β”‚
261
- β”‚ β”œβ”€β”€ styles/ # μŠ€νƒ€μΌ
262
- β”‚ β”‚ └── index.css
263
- β”‚ β”‚
264
- β”‚ β”œβ”€β”€ App.tsx # 루트 μ»΄ν¬λ„ŒνŠΈ
265
- β”‚ β”œβ”€β”€ GameEngine.tsx # κ²Œμž„ μ—”μ§„ μ»΄ν¬λ„ŒνŠΈ
266
- β”‚ └── main.tsx # μ§„μž…μ 
267
- β”‚
268
- β”œβ”€β”€ index.html
269
- β”œβ”€β”€ package.json
270
- β”œβ”€β”€ tsconfig.json
271
- β”œβ”€β”€ vite.config.ts
272
- └── README.md
273
- ```
274
-
275
- ---
276
-
277
- ## 5. νƒ€μž… μ •μ˜
278
-
279
- ```typescript
280
- // types/index.ts
281
-
282
- /** μ’Œν‘œ νƒ€μž… */
283
- export interface Point {
284
- x: number;
285
- y: number;
286
- }
287
-
288
- /** 이동 λ°©ν–₯ */
289
- export type Direction = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT';
290
-
291
- /** κ²Œμž„ μ§„ν–‰ μƒνƒœ */
292
- export type GameStatus = 'IDLE' | 'PLAYING' | 'PAUSED' | 'GAME_OVER';
293
-
294
- /** 전체 κ²Œμž„ μƒνƒœ (Reducer State) */
295
- export interface GameState {
296
- status: GameStatus;
297
- snake: Point[]; // λ±€ λͺΈν†΅ (0번이 머리)
298
- food: Point; // 먹이 μœ„μΉ˜
299
- direction: Direction; // ν˜„μž¬ λ°©ν–₯
300
- nextDirection: Direction; // μž…λ ₯ 버퍼 (λ‹€μŒ 틱에 적용)
301
- score: number;
302
- level: number;
303
- speed: number; // ν˜„μž¬ 속도 (ms)
304
- }
305
-
306
- /** Reducer Actions */
307
- export type GameAction =
308
- | { type: 'START_GAME' }
309
- | { type: 'PAUSE_GAME' }
310
- | { type: 'RESUME_GAME' }
311
- | { type: 'GAME_OVER' }
312
- | { type: 'TICK' }
313
- | { type: 'CHANGE_DIRECTION'; payload: Direction }
314
- | { type: 'EAT_FOOD' }
315
- | { type: 'RESTART' };
316
-
317
- /** κ²Œμž„ μ„€μ • */
318
- export interface GameConfig {
319
- boardSize: number; // κ·Έλ¦¬λ“œ 크기 (20x20)
320
- cellSize: number; // μ…€ ν”½μ…€ 크기
321
- initialSpeed: number; // 초기 속도 (ms)
322
- speedDecrement: number; // λ ˆλ²¨μ—… μ‹œ 속도 κ°μ†ŒλŸ‰
323
- minSpeed: number; // μ΅œμ†Œ 속도 (μ΅œλŒ€ λ‚œμ΄λ„)
324
- pointsPerFood: number; // 먹이당 점수
325
- pointsForLevelUp: number; // λ ˆλ²¨μ—… ν•„μš” 점수
326
- }
327
-
328
- /** ν‚€λ³΄λ“œ ν•Έλ“€λŸ¬ */
329
- export interface KeyboardHandlers {
330
- onDirectionChange: (direction: Direction) => void;
331
- onPause?: () => void;
332
- onRestart?: () => void;
333
- }
334
-
335
- /** μŠ€μ™€μ΄ν”„ ν•Έλ“€λŸ¬ */
336
- export interface SwipeHandlers {
337
- left?: () => void;
338
- right?: () => void;
339
- up?: () => void;
340
- down?: () => void;
341
- }
342
- ```
343
-
344
- ---
345
-
346
- ## 6. κ²Œμž„ μ„€μ • μƒμˆ˜
347
-
348
- ```typescript
349
- // constants/config.ts
350
-
351
- export const GAME_CONFIG: GameConfig = {
352
- boardSize: 20, // 20x20 κ·Έλ¦¬λ“œ
353
- cellSize: 20, // 각 μ…€ 20px
354
- initialSpeed: 150, // 150ms (초기)
355
- speedDecrement: 10, // λ ˆλ²¨μ—… μ‹œ 10ms κ°μ†Œ
356
- minSpeed: 50, // μ΅œμ†Œ 50ms (졜고 λ‚œμ΄λ„)
357
- pointsPerFood: 10, // 먹이당 10점
358
- pointsForLevelUp: 50, // 50μ λ§ˆλ‹€ λ ˆλ²¨μ—…
359
- };
360
-
361
- export const COLORS = {
362
- background: '#1a1a2e',
363
- grid: '#16213e',
364
- snake: '#00ff88',
365
- snakeHead: '#00cc6a',
366
- food: '#ff6b6b',
367
- text: '#ffffff',
368
- };
369
-
370
- export const INITIAL_SNAKE: Point[] = [
371
- { x: 10, y: 10 }, // 머리
372
- { x: 9, y: 10 },
373
- { x: 8, y: 10 },
374
- ];
375
-
376
- export const DIRECTION_VECTORS: Record<Direction, Point> = {
377
- UP: { x: 0, y: -1 },
378
- DOWN: { x: 0, y: 1 },
379
- LEFT: { x: -1, y: 0 },
380
- RIGHT: { x: 1, y: 0 },
381
- };
382
-
383
- export const OPPOSITE_DIRECTIONS: Record<Direction, Direction> = {
384
- UP: 'DOWN',
385
- DOWN: 'UP',
386
- LEFT: 'RIGHT',
387
- RIGHT: 'LEFT',
388
- };
389
- ```
390
-
391
- ---
392
-
393
- ## βœ… μ•„ν‚€ν…μ²˜ 체크리슀트
394
-
395
- - [x] μ»΄ν¬λ„ŒνŠΈ ꡬ쑰 μ •μ˜
396
- - [x] 데이터 흐름 섀계
397
- - [x] μ»€μŠ€ν…€ ν›… 섀계
398
- - [x] 파일/폴더 ꡬ쑰 μ •μ˜
399
- - [x] νƒ€μž… μ •μ˜
400
- - [x] κ²Œμž„ μ„€μ • μƒμˆ˜ μ •μ˜
@@ -1,209 +0,0 @@
1
- # Snake Game - Implementation Rules
2
- # 생성일: 2026-01-21
3
- # μŠ€ν…Œμ΄μ§€: 03-planning
4
-
5
- project:
6
- name: snake-game
7
- type: game
8
- framework: react
9
- language: typescript
10
-
11
- # μ»΄ν¬λ„ŒνŠΈ κ·œμΉ™
12
- components:
13
- type: functional # functional | class
14
- naming: PascalCase
15
- file_extension: tsx
16
-
17
- # μ»΄ν¬λ„ŒνŠΈ ꡬ쑰
18
- structure:
19
- - props_interface # Props μΈν„°νŽ˜μ΄μŠ€ μ •μ˜
20
- - component_function
21
- - exports
22
-
23
- # μ»΄ν¬λ„ŒνŠΈ μΉ΄ν…Œκ³ λ¦¬
24
- categories:
25
- - name: containers
26
- path: src/
27
- examples: [App.tsx, GameEngine.tsx]
28
- - name: presentation
29
- path: src/components/
30
- examples: [CanvasLayer.tsx, ScoreBoard.tsx]
31
- - name: ui
32
- path: src/components/
33
- examples: [GameOverModal.tsx, MobileControls.tsx]
34
-
35
- # μŠ€νƒ€μΌλ§ κ·œμΉ™
36
- styling:
37
- method: css-modules # css-modules | tailwind | styled-components
38
- naming: kebab-case
39
- file_pattern: "{ComponentName}.module.css"
40
-
41
- # 색상 λ³€μˆ˜ (CSS Custom Properties)
42
- colors:
43
- background: "#1a1a2e"
44
- grid: "#16213e"
45
- snake: "#00ff88"
46
- snake_head: "#00cc6a"
47
- food: "#ff6b6b"
48
- text: "#ffffff"
49
-
50
- # μƒνƒœ 관리
51
- state_management:
52
- global: useReducer # context | redux | zustand | useReducer
53
- local: useState
54
- refs: useRef # κ²Œμž„ 루프, Canvas ref
55
-
56
- # μƒνƒœ 뢄리 원칙
57
- principles:
58
- - "UI λ¦¬λ Œλ”λ§ ν•„μš”ν•œ μƒνƒœ β†’ useReducer"
59
- - "λΉ λ₯Έ μ—…λ°μ΄νŠΈ ν•„μš”ν•œ μƒνƒœ β†’ useRef"
60
- - "Canvas DOM μ°Έμ‘° β†’ useRef"
61
-
62
- # ν›… κ·œμΉ™
63
- hooks:
64
- naming: "use{Name}"
65
- location: src/hooks/
66
-
67
- # μ»€μŠ€ν…€ ν›… λͺ©λ‘
68
- custom:
69
- - name: useGameLoop
70
- purpose: requestAnimationFrame 기반 κ²Œμž„ 루프
71
- - name: useKeyboard
72
- purpose: ν‚€λ³΄λ“œ μž…λ ₯ 처리
73
- - name: useSwipe
74
- purpose: ν„°μΉ˜ μŠ€μ™€μ΄ν”„ 감지
75
- - name: useHighScore
76
- purpose: localStorage 졜고점수 관리
77
-
78
- # νƒ€μž… μ •μ˜ κ·œμΉ™
79
- types:
80
- location: src/types/
81
- naming: PascalCase
82
-
83
- # 핡심 νƒ€μž…
84
- core:
85
- - Point
86
- - Direction
87
- - GameStatus
88
- - GameState
89
- - GameAction
90
- - GameConfig
91
-
92
- # μƒμˆ˜ κ·œμΉ™
93
- constants:
94
- location: src/constants/
95
- naming: SCREAMING_SNAKE_CASE
96
-
97
- # 핡심 μƒμˆ˜
98
- core:
99
- - GAME_CONFIG
100
- - COLORS
101
- - INITIAL_SNAKE
102
- - DIRECTION_VECTORS
103
- - OPPOSITE_DIRECTIONS
104
-
105
- # μœ ν‹Έλ¦¬ν‹° κ·œμΉ™
106
- utilities:
107
- location: src/utils/
108
- naming: camelCase
109
-
110
- # μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
111
- functions:
112
- - generateRandomPosition
113
- - isCollision
114
- - isValidDirection
115
-
116
- # 폴더 ꡬ쑰
117
- folder_structure:
118
- type: type-based # feature-based | type-based
119
-
120
- structure:
121
- src:
122
- - components/ # React μ»΄ν¬λ„ŒνŠΈ
123
- - hooks/ # μ»€μŠ€ν…€ ν›…
124
- - engine/ # κ²Œμž„ 둜직 (reducer, collision, renderer)
125
- - types/ # TypeScript νƒ€μž…
126
- - constants/ # μƒμˆ˜
127
- - utils/ # μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
128
- - styles/ # κΈ€λ‘œλ²Œ μŠ€νƒ€μΌ
129
- - assets/ # 정적 μžμ‚°
130
-
131
- # 파일 λͺ…λͺ… κ·œμΉ™
132
- file_naming:
133
- components: PascalCase.tsx
134
- hooks: camelCase.ts
135
- types: index.ts # 단일 파일 λ˜λŠ” camelCase.ts
136
- constants: camelCase.ts
137
- utils: camelCase.ts
138
- styles: index.css λ˜λŠ” {Component}.module.css
139
-
140
- # μž„ν¬νŠΈ κ·œμΉ™
141
- imports:
142
- order:
143
- - react # React κ΄€λ ¨
144
- - external # μ™ΈλΆ€ 라이브러리
145
- - internal # λ‚΄λΆ€ λͺ¨λ“ˆ (μ ˆλŒ€ 경둜)
146
- - relative # μƒλŒ€ 경둜
147
- - styles # μŠ€νƒ€μΌ
148
- - types # νƒ€μž…
149
-
150
- alias:
151
- "@": src/
152
-
153
- # μ½”λ“œ ν’ˆμ§ˆ
154
- code_quality:
155
- eslint: true
156
- prettier: true
157
- typescript_strict: true
158
-
159
- rules:
160
- - "no-any: κ°€λŠ₯ν•œ ν•œ any νƒ€μž… μ‚¬μš© κΈˆμ§€"
161
- - "explicit-return-types: ν•¨μˆ˜ λ°˜ν™˜ νƒ€μž… λͺ…μ‹œ"
162
- - "no-unused-vars: λ―Έμ‚¬μš© λ³€μˆ˜ κΈˆμ§€"
163
-
164
- # ν…ŒμŠ€νŠΈ κ·œμΉ™
165
- testing:
166
- framework: vitest
167
- location: src/__tests__/ λ˜λŠ” μ»΄ν¬λ„ŒνŠΈ μ˜† {name}.test.ts
168
-
169
- coverage_target: 80%
170
-
171
- naming:
172
- unit: "{name}.test.ts"
173
- e2e: "{feature}.e2e.ts"
174
-
175
- # μ„±λŠ₯ κ·œμΉ™
176
- performance:
177
- # Canvas μ΅œμ ν™”
178
- canvas:
179
- - "requestAnimationFrame μ‚¬μš©"
180
- - "μ˜€ν”„μŠ€ν¬λ¦° μΊ”λ²„μŠ€ κ³ λ €"
181
- - "λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§ λ°©μ§€"
182
-
183
- # React μ΅œμ ν™”
184
- react:
185
- - "React.memo ν•„μš”μ‹œ μ‚¬μš©"
186
- - "useCallback/useMemo κ³Όλ„ν•œ μ‚¬μš© 자제"
187
- - "κ²Œμž„ μƒνƒœλŠ” useRef둜 관리"
188
-
189
- # Git 컀밋 κ·œμΉ™
190
- git:
191
- conventional_commits: true
192
-
193
- types:
194
- feat: μƒˆ κΈ°λŠ₯
195
- fix: 버그 μˆ˜μ •
196
- refactor: λ¦¬νŒ©ν† λ§
197
- test: ν…ŒμŠ€νŠΈ
198
- docs: λ¬Έμ„œ
199
- style: ν¬λ§·νŒ…
200
- chore: 기타
201
-
202
- # κΈˆμ§€ 사항
203
- prohibited:
204
- - "μ™ΈλΆ€ κ²Œμž„ μ—”μ§„ (Phaser, PixiJS λ“±)"
205
- - "jQuery"
206
- - "Class μ»΄ν¬λ„ŒνŠΈ (ν•¨μˆ˜ν˜•λ§Œ μ‚¬μš©)"
207
- - "any νƒ€μž… λ‚¨μš©"
208
- - "μ „μ—­ λ³€μˆ˜"
209
- - "setInterval (requestAnimationFrame λŒ€μ‹  μ‚¬μš©)"