diff --git a/00_Raw/.gitkeep b/01_Archive/2026-04-20/.gitkeep similarity index 100% rename from 00_Raw/.gitkeep rename to 01_Archive/2026-04-20/.gitkeep diff --git a/01_Archive/2026-04-20/01_WebWorker-performance-optimization.md b/01_Archive/2026-04-20/01_WebWorker-performance-optimization.md new file mode 100644 index 00000000..a2d6c91d --- /dev/null +++ b/01_Archive/2026-04-20/01_WebWorker-performance-optimization.md @@ -0,0 +1,20 @@ +--- +# ๐ก Lesson Learned: Web Worker๋ฅผ ์ด์ฉํ ๊ณ ์ฑ๋ฅ ์ํคํ ์ฒ ์ค๊ณ (Performance) + +## ๐ฏ ๋ฌธ์ ์ํฉ (The Problem) +ํ ํธ๋ฆฌ์ค ๊ฒ์๊ณผ ๊ฐ์ด **๋งค์ฐ ๋์ ๋น๋(High Frequency)**๋ก ์ํ ๋ณํ๊ฐ ๋ฐ์ํ๋ ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ React์ ๋ฉ์ธ ์ค๋ ๋์์ ์ฒ๋ฆฌํ ๊ฒฝ์ฐ, UI ์ ๋ฐ์ดํธ์ ๋ฌผ๋ฆฌ ๊ณ์ฐ์ด ์ถฉ๋ํ์ฌ **ํ๋ ์ ๋๋กญ(Jank)** ํ์์ด๋ ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ์ต๋๋ค. + +## ๐ฌ ๊ทผ๋ณธ ์์ธ (Root Cause) +๊ฒ์ ์์ง ๋ก์ง์ CPU๋ฅผ ๋งค์ฐ ๋ง์ด ์ฌ์ฉํฉ๋๋ค. ์ด ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ ๋ฉ์ธ ์ค๋ ๋์์ ์ํํ๋ฉด, ๋ธ๋ผ์ฐ์ ์ UI ์ ๋ฐ์ดํธ ๋ฃจํ(`requestAnimationFrame`)์ ์ถฉ๋ํ์ฌ ์ฌ์ฉ์์๊ฒ ๋ถ๋๋ฝ์ง ์์ ๊ฒฝํ(Poor UX)์ ์ ๊ณตํ๊ฒ ๋ฉ๋๋ค. + +## โ ํด๊ฒฐ์ฑ (The Solution) +**Web Worker**๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ ์์ง ๋ก์ง ์ ์ฒด๋ฅผ **๋ฉ์ธ ์ค๋ ๋์์ ์์ ํ ๋ถ๋ฆฌ(Isolate)** ํ์ต๋๋ค. +* **์๋ฆฌ:** Web Worker๋ ๋ณ๋์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ๋์ํ๋ฏ๋ก, ์๋ฌด๋ฆฌ ๋ณต์กํ ๊ณ์ฐ์ ํด๋ ๋ฉ์ธ ์ค๋ ๋์ UI ๋ ๋๋ง์๋ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค. + +## ๐ก ๊ตํ (Lesson Learned) +> **"์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ข ์ข '์ค๋ ๋ฉ(Threading)'์ ๋ฌธ์ ์ด๋ค."** +> ์ค์๊ฐ์ผ๋ก ๋์ ์ฐ์ฐ๋์ด ์๊ตฌ๋๋ ๋ชจ๋ ์์คํ ์, ๋ฐ๋์ Web Worker ๋๋ ๋ณ๋์ ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค๋ก ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. + +## ๐ ๊ด๋ จ ํค์๋ +`Web Worker`, `Concurrency`, `High-Frequency Updates`, `Performance Optimization` +--- \ No newline at end of file diff --git a/01_Archive/2026-04-20/02_StateManagement-single-source-of-truth.md b/01_Archive/2026-04-20/02_StateManagement-single-source-of-truth.md new file mode 100644 index 00000000..904c55a0 --- /dev/null +++ b/01_Archive/2026-04-20/02_StateManagement-single-source-of-truth.md @@ -0,0 +1,19 @@ +--- +# ๐ก Lesson Learned: ์ํ ๊ด๋ฆฌ์ ๋จ์ผ ์ง์ค ๊ณต๊ธ์ ์์น (Data Consistency) + +## ๐ฏ ๋ฌธ์ ์ํฉ (The Problem) +ํ ํธ๋ฆฌ์ค ๊ฒ์์ 'ํ์ฌ ๋ณด๋ ์ํ'์ '์์ง์ด๋ ๋ธ๋ก ์์น'๋ผ๋ ๋ ๊ฐ์ง ํต์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด ๋ฐ์ดํฐ๋ค์ด ์ฌ๋ฌ ๊ณณ์์ ๋ ๋ฆฝ์ ์ผ๋ก ์ ๋ฐ์ดํธ๋ ์ํ์ด ์์์ต๋๋ค. ๋ง์ฝ A ๋ถ๋ถ์์ ๊ฐ์ ๋ฐ๊พธ๊ณ , B ๋ถ๋ถ์์ ๊ฐ์ ๊ฐ์ ๋ค๋ฅด๊ฒ ๊ณ์ฐํ๋ค๋ฉด **๋ฐ์ดํฐ ๋ถ์ผ์น(Inconsistency)**๊ฐ ๋ฐ์ํฉ๋๋ค. + +## ๐ฌ ๊ทผ๋ณธ ์์ธ (Root Cause) +์์คํ ์ ํต์ฌ ์ํ๊ฐ ๋ถ์ฐ๋์ด ๊ด๋ฆฌ๋๊ณ ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฌ๋ฌ ์ปดํฌ๋ํธ์ ๋ก์ง์ด ๊ฐ์ '์ง์ค'์ด๋ผ๊ณ ๋ฏฟ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ถฉ๋ํ ๊ฐ๋ฅ์ฑ์ด ๋์์ต๋๋ค. + +## โ ํด๊ฒฐ์ฑ (The Solution) +**Redux/Zustand ํจํด์ ์ฐจ์ฉํ์ฌ ๋ชจ๋ ๊ฒ์์ ํต์ฌ ์ํ(State)**๋ฅผ `src/TetrisGame.jsx` ์ปดํฌ๋ํธ๊ฐ ๊ด๋ฆฌํ๋ **๋จ์ผ ์ง์ (Single Source of Truth)**์ผ๋ก ๋ง๋ค์์ต๋๋ค. ๋ชจ๋ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ด ์ค์ ์ ์ฅ์๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๊ฒ ํ์ต๋๋ค. + +## ๐ก ๊ตํ (Lesson Learned) +> **"์ํ๋ ์ค์ง ํ ๊ณณ์์๋ง ์ ์ํ๊ณ , ๋ชจ๋ ๋ก์ง์ ๊ทธ ์ํ๋ฅผ ์ฝ๊ณ ์ฐ๋ ๋ฐฉ์์ผ๋ก ๋์ํด์ผ ํ๋ค."** +> ๋ณต์กํ ์์คํ ์ ์ค๊ณํ ๋, ํต์ฌ ๋ฐ์ดํฐ์ ํ๋ฆ(Data Flow)๊ณผ ์ฑ ์ ๋ฒ์(Responsibility)๋ฅผ ๋ช ํํ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ค์ํฉ๋๋ค. + +## ๐ ๊ด๋ จ ํค์๋ +`Single Source of Truth`, `Redux Pattern`, `State Management`, `Predictable State` +--- \ No newline at end of file diff --git a/01_Archive/2026-04-20/03_Architecture-design-principle.md b/01_Archive/2026-04-20/03_Architecture-design-principle.md new file mode 100644 index 00000000..957942cd --- /dev/null +++ b/01_Archive/2026-04-20/03_Architecture-design-principle.md @@ -0,0 +1,22 @@ +--- +# ๐ก Lesson Learned: ์์คํ ์ํคํ ์ฒ์ ์ค์์ฑ (The Need for Abstraction) + +## ๐ฏ ๋ฌธ์ ์ํฉ (The Problem) +์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์, ์ฝ๋๋ฅผ ์ง๋ ๊ฒ์ด ์๋๋ผ '์ด๋ค ๊ตฌ์กฐ๋ก ์งค์ง'๊ฐ ๊ฐ์ฅ ์ด๋ ค์ ์ต๋๋ค. ์ด๋ ๋จ์ํ ๊ธฐ์ ์ ์ธ ๋ฌธ์ ๊ฐ ์๋ **์ค๊ณ ํจํด(Design Pattern)**๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ์ ๋๋ค. + +## ๐ฌ ๊ทผ๋ณธ ์์ธ (Root Cause) +๋ชจ๋ ๋ก์ง์ ํ ํ์ผ์ ๋๋ ค ๋ฃ์ผ๋ ค๋ ์ ํน์ ๋น ์ง๋ ๊ฒ, ์ฆ '์คํ๊ฒํฐ ์ฝ๋'๋ฅผ ๋ง๋ค ์ํ์ด ๊ฐ์ฅ ํฐ ๋ฌธ์ ์์ต๋๋ค. ๋ชจ๋ ๊ฒ์ ํ๊ณณ์์ ์ฒ๋ฆฌํ๋ ค ํ๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ด 0์ ์๋ ดํ์ต๋๋ค. + +## โ ํด๊ฒฐ์ฑ (The Solution) +**์ํคํ ์ฒ์ ๋ถ๋ฆฌ ์์น(Separation of Concerns, SoC)**์ ์ ์ฉํ์ฌ ์ฝ๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ญํ ๋ณ๋ก ๋๋ด์ต๋๋ค: +1. **๊ฒ์ ๊ท์น:** `gameWorker.js` (๋ ผ๋ฆฌ ์์ง) +2. **์ํ ๊ด๋ฆฌ:** `TetrisGame.jsx` (๋ฐ์ดํฐ์ ์ถ์ ๊ตฌ) +3. **๋ ๋๋ง:** React ์ปดํฌ๋ํธ (ํ๋ฉด์ ๋ณด์ฌ์ฃผ๋ ์ญํ ๋ง ์ํ) + +## ๐ก ๊ตํ (Lesson Learned) +> **"์์คํ ์ ๊ตฌ์ฑํ ๋๋ '์ฑ ์ ๋ถ๋ฆฌ(Separation of Concerns)'๋ฅผ ์ต์ฐ์ ์์น์ผ๋ก ์ผ์์ผ ํ๋ค."** +> ๊ธฐ๋ฅ์ด ๋ณต์กํด์ง์๋ก, ์ฝ๋๋ ๋ฐ๋์ ๊ฒฝ๊ณ๊ฐ ๋ช ํํ ๋ชจ๋๋ค๋ก ๋ถ๋ฆฌ๋์ด์ผ ํฉ๋๋ค. + +## ๐ ๊ด๋ จ ํค์๋ +`Separation of Concerns`, `Modular Design`, `Microservices Pattern` +--- \ No newline at end of file diff --git a/01_Archive/2026-04-20/04_execution-environment-management.md b/01_Archive/2026-04-20/04_execution-environment-management.md new file mode 100644 index 00000000..4f30447c --- /dev/null +++ b/01_Archive/2026-04-20/04_execution-environment-management.md @@ -0,0 +1,22 @@ +--- +# ๐ก Lesson Learned: ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐ ์คํ ํ๋ก์ธ์ค ๊ด๋ฆฌ (DevOps & DevOps) + +## ๐ฏ ๋ฌธ์ ์ํฉ (The Problem) +์ด๋ฒ ํ๋ก์ ํธ๋ ๋จ์ํ ์ฝ๋๋ฅผ ์ง๊ณ ๋๋๋ ๊ฒ์ด ์๋๋ผ, **'์ด๋ป๊ฒ ์ด ์ฝ๋๋ฅผ ๊ตฌ๋์ํฌ ์ ์๋๊ฐ?'**๋ผ๋ ๋ฌผ๋ฆฌ์ ์ ์ฐจ์ ์ค์์ฑ์ ๊นจ๋ฌ์์ต๋๋ค. (์ค๋ฅ ์ฝ๋: `npm audit`, `index.html` ๋๋ฝ, ๊ถํ ์ค๋ฅ ๋ฑ) + +## ๐ฌ ๊ทผ๋ณธ ์์ธ (Root Cause) +๊ฐ๋ฐ์๋ ์ข ์ข **'๋ ผ๋ฆฌ์ ์์ฑ๋(Logical Completion)'์๋ง ์ง์ค**ํ๊ณ , ํ๋ก์ ํธ๋ฅผ ์คํํ๋ ๋ฐ ํ์ํ **๋ฌผ๋ฆฌ์ ์ธ ์ค์ ํ์ผ(Configuration)**๊ณผ **์ด์์ฒด์ ๋ ๋ฒจ์ ํ๊ฒฝ ๋ณ์/๊ถํ** ๊ด๋ฆฌ์ ์ํํด์ง๊ธฐ ์ฝ์ต๋๋ค. + +## โ ํด๊ฒฐ์ฑ (The Solution) +ํ๋ก์ ํธ ์์ ์์ ์ ๋ค์ ์ ์ฐจ๋ฅผ ๋ฐ๋์ ๊ฑฐ์ณ์ผ ํจ์ ํ๋ฆฝํ์ต๋๋ค: +1. `npm install`: ํ์ํ ๋ชจ๋ ํจํค์ง๋ฅผ ์ค์นํ๋ค. +2. ํ๊ฒฝ ์ค์ ํ์ธ: `public/index.html` ๋ฑ ํ์ ์ง์ ์ ์ด ์กด์ฌํ๋์ง ํ์ธํ๋ค. +3. ๊ถํ ํ๋ณด: ์ด์์ฒด์ ๋ ๋ฒจ์์ ์คํฌ๋ฆฝํธ ์คํ ๊ถํ(Execution Policy)์ ํ๋ณดํ๋ค. + +## ๐ก ๊ตํ (Lesson Learned) +> **"์ฝ๋ฉ ๋ฅ๋ ฅ๋งํผ์ด๋ ์ค์ํ ๊ฒ์ '์ด์ ํ๊ฒฝ์ ๋ํ ์ดํด'์ '์ฒด๊ณ์ ์ธ ๊ฐ๋ฐ ํ๋ก์ธ์ค ํ๋ฆฝ'์ด๋ค."** +> ํ๋ก์ ํธ ๊ด๋ฆฌ์๋ ํญ์ ์ด ์ธ ๊ฐ์ง ๋จ๊ณ๋ฅผ ์ ๊ฒํด์ผ ํฉ๋๋ค. + +## ๐ ๊ด๋ จ ํค์๋ +`DevOps`, `CI/CD Pipeline`, `Execution Policy`, `Build Environment` +--- \ No newline at end of file diff --git a/01_Archive/2026-04-20/05_simulation-design-principles.md b/01_Archive/2026-04-20/05_simulation-design-principles.md new file mode 100644 index 00000000..e3615026 --- /dev/null +++ b/01_Archive/2026-04-20/05_simulation-design-principles.md @@ -0,0 +1,19 @@ +--- +# ๐ก Lesson Learned: ์์คํ ์๋ฎฌ๋ ์ด์ ์ ํต์ฌ ์๋ฆฌ (Simulation Design) + +## ๐ฏ ๋ฌธ์ ์ํฉ (The Problem) +ํ ํธ๋ฆฌ์ค๋ ๋จ์ํ ๊ฒ์์ด ์๋๋ผ, **๋ฌผ๋ฆฌ ๋ฒ์น(Physics)**๊ณผ **๊ท์น ๊ธฐ๋ฐ์ ์ํ ๋ณํ**๊ฐ ์๋ํ๋ ์์ ์๋ฎฌ๋ ์ดํฐ์์ต๋๋ค. ์ด ๊ฒฝํ์ ํตํด '์๋ฎฌ๋ ์ด์ ์ ์ด๋ป๊ฒ ์ค๊ณํด์ผ ํ๋์ง'์ ๋ํ ๊น์ ์ดํด๋ฅผ ์ป์์ต๋๋ค. + +## ๐ฌ ๊ทผ๋ณธ ์์ธ (Root Cause) +๋จ์ํ UI๋ก ๊ทธ๋ฆฌ๋ ๊ฒ์๋ง ์ง์คํ๋ฉด, ์์คํ ์ด **๊ท์น(Ruleset)**๊ณผ **๋ฌผ๋ฆฌ ๋ฒ์น(Physics Law)**์ ๋ฐ๋ฅด๋ '๊ฐ์ ์ธ๊ณ'์ ๋๋์ ๋์น๊ธฐ ์ฝ์ต๋๋ค. + +## โ ํด๊ฒฐ์ฑ (The Solution) +๊ฒ์ ๋ก์ง์ `gameWorker.js`์ ์์ ํ ๋ถ๋ฆฌํ์ฌ, ๋ชจ๋ ๋ณํ๋ฅผ ์ํ์ ํจ์(`checkCollision`, `movePiece`)๋ก ์ฒ๋ฆฌํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ํ(State)์ ๋ฐ์ํ์ต๋๋ค. ์ด๋ ๊ณง **"๊ท์น์ด ๋ฌผ๋ฆฌ ๋ฒ์น์ฒ๋ผ ์๋ํ๋ ์์คํ "** ์ค๊ณ์ ์ฑ๊ณต์ ์ธ ์์์ ๋๋ค. + +## ๐ก ๊ตํ (Lesson Learned) +> **"๋ชจ๋ ์๋ฎฌ๋ ์ด์ ์ '๋ฌผ๋ฆฌ์ ๊ท์น'์ ์ํ์ ์ผ๋ก ์ ์ํ๊ณ , ๊ทธ ๊ท์น์ ์ ๋ ์ฐํํ ์ ์๋๋ก ๊ฐ์ ํด์ผ ํ๋ค."** +> ์ด๋ฅผ ํตํด ์ฐ๋ฆฌ๋ ๋จ์ํ ๊ฒ์์ ๋์ด, ์์จ์ฃผํ์ด๋ ๋ฌผ๋ฆฌ ์์ง์ ์ ์ฉ ๊ฐ๋ฅํ ๊ณ ์์ค์ ์์คํ ๋ชจ๋ธ๋ง ๋ฅ๋ ฅ์ ๊ฐ์ถ๊ฒ ๋์์ต๋๋ค. + +## ๐ ๊ด๋ จ ํค์๋ +`Simulation Design`, `Physics Engine`, `Ruleset Enforcement`, `Systemic Modeling` +--- \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/app.json b/10_Wiki/Topics/.obsidian/app.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/10_Wiki/Topics/.obsidian/app.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/appearance.json b/10_Wiki/Topics/.obsidian/appearance.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/10_Wiki/Topics/.obsidian/appearance.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/core-plugins.json b/10_Wiki/Topics/.obsidian/core-plugins.json new file mode 100644 index 00000000..639b90da --- /dev/null +++ b/10_Wiki/Topics/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "footnotes": false, + "properties": true, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": true, + "bases": true, + "webviewer": false +} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/graph.json b/10_Wiki/Topics/.obsidian/graph.json new file mode 100644 index 00000000..e56c2134 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/graph.json @@ -0,0 +1,22 @@ +{ + "collapse-filter": true, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": true, + "colorGroups": [], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 0.08317427835927536, + "close": false +} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/workspace.json b/10_Wiki/Topics/.obsidian/workspace.json new file mode 100644 index 00000000..a2ee0147 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/workspace.json @@ -0,0 +1,187 @@ +{ + "main": { + "id": "59f0bd68c638b9ae", + "type": "split", + "children": [ + { + "id": "6e3e7f0212dd6d2e", + "type": "tabs", + "children": [ + { + "id": "5e19c94f304a33d1", + "type": "leaf", + "state": { + "type": "graph", + "state": {}, + "icon": "lucide-git-fork", + "title": "๊ทธ๋ํ ๋ทฐ" + } + } + ] + } + ], + "direction": "vertical" + }, + "left": { + "id": "b20f341b7d225db0", + "type": "split", + "children": [ + { + "id": "76facd68bdc37a30", + "type": "tabs", + "children": [ + { + "id": "697d93dc46e83f99", + "type": "leaf", + "state": { + "type": "file-explorer", + "state": { + "sortOrder": "alphabetical", + "autoReveal": false + }, + "icon": "lucide-folder-closed", + "title": "ํ์ผ ํ์๊ธฐ" + } + }, + { + "id": "14386382787eb545", + "type": "leaf", + "state": { + "type": "search", + "state": { + "query": "", + "matchingCase": false, + "explainSearch": false, + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical" + }, + "icon": "lucide-search", + "title": "๊ฒ์" + } + }, + { + "id": "6544f7f2d2bdb927", + "type": "leaf", + "state": { + "type": "bookmarks", + "state": {}, + "icon": "lucide-bookmark", + "title": "๋ถ๋งํฌ" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300 + }, + "right": { + "id": "eb1afd59f22726e4", + "type": "split", + "children": [ + { + "id": "cff2bf89b29bbdad", + "type": "tabs", + "children": [ + { + "id": "a06f05e29da92edb", + "type": "leaf", + "state": { + "type": "backlink", + "state": { + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical", + "showSearch": false, + "searchQuery": "", + "backlinkCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-coming-in", + "title": "๋ฐฑ๋งํฌ" + } + }, + { + "id": "461414a74ff42c5f", + "type": "leaf", + "state": { + "type": "outgoing-link", + "state": { + "linksCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-going-out", + "title": "๋๊ฐ๋ ๋งํฌ" + } + }, + { + "id": "2c463caabad51324", + "type": "leaf", + "state": { + "type": "tag", + "state": { + "sortOrder": "frequency", + "useHierarchy": true, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-tags", + "title": "ํ๊ทธ" + } + }, + { + "id": "e863614ec11ec6c0", + "type": "leaf", + "state": { + "type": "all-properties", + "state": { + "sortOrder": "frequency", + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-archive", + "title": "๋ชจ๋ ์์ฑ" + } + }, + { + "id": "0f1cc972aeac180a", + "type": "leaf", + "state": { + "type": "outline", + "state": { + "followCursor": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-list", + "title": "๊ฐ์" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300, + "collapsed": true + }, + "left-ribbon": { + "hiddenItems": { + "switcher:๋น ๋ฅธ ์ ํ๊ธฐ ์ด๊ธฐ": false, + "graph:๊ทธ๋ํ ๋ทฐ ์ด๊ธฐ": false, + "canvas:์ ์บ๋ฒ์ค ๋ง๋ค๊ธฐ": false, + "daily-notes:์ค๋์ ์ผ์ผ ๋ ธํธ ์ด๊ธฐ": false, + "templates:ํ ํ๋ฆฟ ์ฝ์ ": false, + "command-palette:๋ช ๋ น์ด ํ๋ ํธ ์ด๊ธฐ": false, + "bases:์ ๋ฒ ์ด์ค ์์ฑํ๊ธฐ": false + } + }, + "active": "5e19c94f304a33d1", + "lastOpenFiles": [ + "Systemic_Simulation_Principles.md", + "DevOps_Environment_Setup.md", + "Separation_of_Concerns.md", + "Single_Source_of_Truth.md", + "WebWorker_Performance.md" + ] +} \ No newline at end of file diff --git a/10_Wiki/Topics/DevOps_Environment_Setup.md b/10_Wiki/Topics/DevOps_Environment_Setup.md new file mode 100644 index 00000000..c24517d5 --- /dev/null +++ b/10_Wiki/Topics/DevOps_Environment_Setup.md @@ -0,0 +1,24 @@ +--- +title: ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐ ์คํ ํ๋ก์ธ์ค ๊ด๋ฆฌ (DevOps & Setup) +category: DevOps +tags: [DevOps, Environment, CI/CD, Process Management] +created: 2026-04-20 +--- + +# ๊ฐ๋ฐ ํ๊ฒฝ ๋ฐ ์คํ ํ๋ก์ธ์ค ๊ด๋ฆฌ + +## ๐ฏ ๊ฐ์ (Overview) +์ฝ๋ฉ ์์ฑ๋๋งํผ์ด๋ ์ค์ํ **์คํ ํ๊ฒฝ(Runtime Environment)**๊ณผ **์ค์ ํ์ผ(Configuration)**์ ๋ฌด๊ฒฐ์ฑ์ ํ๋ณดํ์ฌ, '๋ด ์ปดํจํฐ์์ ๋๋๋ฐ ์ ์ ๊ธฐ์ ์ ๋์ง?'๋ผ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ํ๋ก์ธ์ค์ ๋๋ค. + +## ๐ ํ์ ์ฒดํฌ๋ฆฌ์คํธ (Checklist) +- **์์กด์ฑ ๊ด๋ฆฌ**: `npm install` ๋ฑ ํจํค์ง ๋ฌด๊ฒฐ์ฑ ํ์ธ. +- **๋ฌผ๋ฆฌ์ ํ์ผ ๊ตฌ์กฐ**: `index.html` ๋ฑ ํ์ ์ง์ ์ ํ์ผ ์กด์ฌ ํ์ธ. +- **๋ณด์ ๋ฐ ๊ถํ**: OS ๋ ๋ฒจ์ ์คํ ์ ์ฑ (`Execution Policy`) ๋ฐ ๊ถํ ์ค์ . + +## ๐ก ๋ ์จ ๋ฐ (Lesson Learned) +> [!NOTE] +> **"์ด์ ํ๊ฒฝ์ ๋ํ ์ดํด๋ ์ฝ๋ฉ ๋ฅ๋ ฅ์ ์ ๋ฐ์ด๋ค."** +> ๋ ผ๋ฆฌ์ ๋ก์ง์ ์์ฑ๋ฟ๋ง ์๋๋ผ, ๊ทธ๊ฒ์ด ์ค์ ๋ก ๊ตฌ๋๋๋ ๋ฌผ๋ฆฌ์ ์ธํ๋ผ ์ค์ ์ ๋ฌธ์ํํ๊ณ ์๋ํํ๋ ๋ฅ๋ ฅ์ด ํ์์ ์ ๋๋ค. + +## ๐ ์ฐ๊ฒฐ๋ ์ง์ +- [[Systemic_Simulation_Principles]] diff --git a/10_Wiki/Topics/Separation_of_Concerns.md b/10_Wiki/Topics/Separation_of_Concerns.md new file mode 100644 index 00000000..e57cf8eb --- /dev/null +++ b/10_Wiki/Topics/Separation_of_Concerns.md @@ -0,0 +1,25 @@ +--- +title: ์์คํ ์ํคํ ์ฒ์ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ (Separation of Concerns) +category: Software Architecture +tags: [Architecture, SoC, Modular Design, Design Pattern] +created: 2026-04-20 +--- + +# ์์คํ ์ํคํ ์ฒ์ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ (SoC) + +## ๐ฏ ๊ฐ์ (Overview) +๋ณต์กํ ์ํํธ์จ์ด ์์คํ ์ ์ญํ ๋ณ๋ก ๊ตฌ๋ถ๋ ๋ ๋ฆฝ์ ์ธ ๋ชจ๋๋ก ๋๋์ด, ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ๊ทน๋ํํ๋ ์ค๊ณ ์ฒ ํ์ ๋๋ค. + +## ๐ ๊ณ์ธต๊ตฌ์กฐ ์์ (Layering Example) +1. **Logic Engine**: ์์ ๋น์ฆ๋์ค ๋ก์ง ๋ฐ ๊ท์น ์ํ (์: `gameWorker.js`) +2. **State Manager**: ๋ฐ์ดํฐ์ ์ค์ ์ง์ค ์ฒ๋ฆฌ (์: `TetrisGame.jsx`) +3. **View Layer**: ์ฌ์ฉ์ ์ธํฐํ์ด์ค ํํ ๋ฐ ๋ ๋๋ง (์: React Components) + +## ๐ก ๋ ์จ ๋ฐ (Lesson Learned) +> [!IMPORTANT] +> **"์ฝ๋์ ๊ฒฝ๊ณ๊ฐ ๋ช ํํ ๋ ์์คํ ์ ๋น๋ก์ ๊ฑด๊ฐํด์ง๋ค."** +> ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋ ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํ๊ธฐ๋ณด๋ค ์๋ก์ด ๋ชจ๋์ ๋ง๋ถ์ผ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ๊ณ ๋ฏผํด์ผ ํฉ๋๋ค. + +## ๐ ์ฐ๊ฒฐ๋ ์ง์ +- [[WebWorker_Performance]] +- [[Single_Source_of_Truth]] diff --git a/10_Wiki/Topics/Single_Source_of_Truth.md b/10_Wiki/Topics/Single_Source_of_Truth.md new file mode 100644 index 00000000..d62c92be --- /dev/null +++ b/10_Wiki/Topics/Single_Source_of_Truth.md @@ -0,0 +1,24 @@ +--- +title: ์ํ ๊ด๋ฆฌ์ ๋จ์ผ ์ง์ค ๊ณต๊ธ์ (Single Source of Truth) +category: Software Architecture +tags: [State Management, Data Consistency, Redux, Architecture] +created: 2026-04-20 +--- + +# ์ํ ๊ด๋ฆฌ์ ๋จ์ผ ์ง์ค ๊ณต๊ธ์ (Single Source of Truth) + +## ๐ฏ ๊ฐ์ (Overview) +์์คํ ์ ํต์ฌ ๋ฐ์ดํฐ๋ฅผ ์ค์ ์ง์ค์์ผ๋ก ๊ด๋ฆฌํ์ฌ, ๋ฐ์ดํฐ ๋ถ์ผ์น(Inconsistency) ํ์์ ์์ฒ ์ฐจ๋จํ๊ณ ์์ธก ๊ฐ๋ฅํ ๋ฐ์ดํฐ ํ๋ฆ์ ํ๋ณดํ๋ ์ค๊ณ ์์น์ ๋๋ค. + +## ๐ ์ฃผ์ ์์น (Key Principles) +- **๋จ์ผ ์ง์ ์ ์ (Defined at Single Point)**: ์ํ๋ ์ค์ง ํ ๊ณณ์์๋ง ์ ์๋๊ณ ๊ด๋ฆฌ๋์ด์ผ ํฉ๋๋ค. +- **์์ธก ๊ฐ๋ฅ์ฑ (Predictability)**: ์ํ ๋ณ๊ฒฝ์ ์ ํด์ง ๊ท์น(Action/Setter)์ ํตํด์๋ง ๋ฐ์ํ์ฌ ๋๋ฒ๊น ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค. + +## ๐ก ๋ ์จ ๋ฐ (Lesson Learned) +> [!TIP] +> **"์ํ๋ ์ค์ง ํ ๊ณณ์์๋ง ์ ์ํ๊ณ , ๋ชจ๋ ๋ก์ง์ ๊ทธ ์ํ๋ฅผ ์ฝ๊ณ ์ฐ๋ ๋ฐฉ์์ผ๋ก ๋์ํด์ผ ํ๋ค."** +> ์ฝ๋์ ํํธํ๋ฅผ ๋ง๊ธฐ ์ํด ๋ฐ์ดํฐ์ ์ฑ ์ ๋ฒ์(Responsibility)๋ฅผ ๋ช ํํ ํ๋ ๊ฒ์ด ๋๊ท๋ชจ ํ๋ก์ ํธ ์ฑ๊ณต์ ์ด์ ์ ๋๋ค. + +## ๐ ์ฐ๊ฒฐ๋ ์ง์ +- [[Separation_of_Concerns]] +- [[Domain-Driven Design (DDD)]] diff --git a/10_Wiki/Topics/Systemic_Simulation_Principles.md b/10_Wiki/Topics/Systemic_Simulation_Principles.md new file mode 100644 index 00000000..3cf8eceb --- /dev/null +++ b/10_Wiki/Topics/Systemic_Simulation_Principles.md @@ -0,0 +1,24 @@ +--- +title: ์์คํ ์๋ฎฌ๋ ์ด์ ์ค๊ณ ์๋ฆฌ +category: Systemic Modeling & Fun +tags: [Simulation, Physics Engine, Systemic Modeling, Ruleset] +created: 2026-04-20 +--- + +# ์์คํ ์๋ฎฌ๋ ์ด์ ์ค๊ณ ์๋ฆฌ + +## ๐ฏ ๊ฐ์ (Overview) +ํ์ค ์ธ๊ณ์ ๋ฌผ๋ฆฌ ๋ฒ์น์ด๋ ๋น์ฆ๋์ค ๊ท์น์ ์ํ์ ์ผ๋ก ์ ์ํ๊ณ , ์ด๋ฅผ ์ ๋์ ์ผ๋ก ์ฐํํ ์ ์๋ ์์คํ ๋ด์ ๋ฒ(Law)์ผ๋ก ๊ตฌ์ถํ๋ ์ค๊ณ ๊ธฐ๋ฒ์ ๋๋ค. + +## ๐ ํต์ฌ ๋ฉ์ปค๋์ฆ (Mechanisms) +- **๊ท์น ๊ฐ์ (Ruleset Enforcement)**: ๋ชจ๋ ์ํ ๋ณํ๋ ์ฌ์ ์ ์ ์๋ ๋ฌผ๋ฆฌ ์์ง ํจ์(`checkCollision` ๋ฑ)๋ฅผ ๊ฑฐ์ณ์ผ๋ง ํฉ๋๋ค. +- **์ํ์ ๋ชจ๋ธ๋ง**: ๋ณํ๋ฅผ ์๊ฐ์ ๋ฌ์ฌ๊ฐ ์๋ ๋ฐ์ดํฐ์ ์์์ผ๋ก ๋จผ์ ์ฆ๋ช ํฉ๋๋ค. + +## ๐ก ๋ ์จ ๋ฐ (Lesson Learned) +> [!TIP] +> **"๋ชจ๋ ์๋ฎฌ๋ ์ด์ ์ ์ํ์ ๊ท์น์ ์ ๋ ์ฐํํ ์ ์๋๋ก ๊ฐ์ ํด์ผ ํ๋ค."** +> ์ด๋ฅผ ํตํด ๋จ์ํ ๊ฒ์์ ๋์ด ์์จ์ฃผํ, ๋ฌผ๋ฆฌ ์์ง ๋ฑ ๊ณ ๋์ ๊ฒฐ์ ๋ก ์ ์์คํ ๋ชจ๋ธ๋ง์ด ๊ฐ๋ฅํด์ง๋๋ค. + +## ๐ ์ฐ๊ฒฐ๋ ์ง์ +- [[WebWorker_Performance]] +- [[Separation_of_Concerns]] diff --git a/10_Wiki/Topics/WebWorker_Performance.md b/10_Wiki/Topics/WebWorker_Performance.md new file mode 100644 index 00000000..0dae6511 --- /dev/null +++ b/10_Wiki/Topics/WebWorker_Performance.md @@ -0,0 +1,24 @@ +--- +title: WebWorker๋ฅผ ์ด์ฉํ ๊ณ ์ฑ๋ฅ ์ํคํ ์ฒ ์ค๊ณ +category: Web & Performance +tags: [Web Worker, Concurrency, Performance, UI responsiveness] +created: 2026-04-20 +--- + +# WebWorker๋ฅผ ์ด์ฉํ ๊ณ ์ฑ๋ฅ ์ํคํ ์ฒ ์ค๊ณ + +## ๐ฏ ๊ฐ์ (Overview) +์ค์๊ฐ ์ํ ๋ณํ๊ฐ ๋งค์ฐ ๋น๋ฒํ ์ ํ๋ฆฌ์ผ์ด์ (์: ๊ฒ์, ์๋ฎฌ๋ ์ด์ )์์ UI ์ค๋ ๋์ ๋ณต์กํ ์ฐ์ฐ ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ **ํ๋ ์ ๋๋กญ(Jank)**์ ๋ฐฉ์งํ๋ ์ํคํ ์ฒ ์ค๊ณ ๊ธฐ๋ฒ์ ๋๋ค. + +## ๐ ์ฃผ์ ์์น (Key Principles) +- **์ค๋ ๋ ๋ถ๋ฆฌ (Thread Isolation)**: ๋ฌด๊ฑฐ์ด ๊ณ์ฐ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋(Web Worker)์์ ์ํํ๊ณ , ๋ฉ์ธ ์ค๋ ๋๋ ๋ ๋๋ง์๋ง ์ง์คํฉ๋๋ค. +- **๋ฉ์์ง ๊ธฐ๋ฐ ํต์ (Messaging Architecture)**: `postMessage`์ `onmessage`๋ฅผ ํตํด ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถฅ๋๋ค. + +## ๐ก ๋ ์จ ๋ฐ (Lesson Learned) +> [!IMPORTANT] +> **"์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ข ์ข '์ค๋ ๋ฉ(Threading)'์ ๋ฌธ์ ์ด๋ค."** +> ๋ณต์กํ ๋ฌผ๋ฆฌ ๊ณ์ฐ์ด๋ ๋ฃจํ๊ฐ UI ์๋ต์ฑ์ ํด์น์ง ์๋๋ก, ์ฐ์ฐ ์์ง์ ์์ ํ ๋ณ๋์ ์ค๋ ๋๋ก ๊ฒฉ๋ฆฌํ๋ ๊ฒ์ด ๋ถ๋๋ฌ์ด UX์ ํต์ฌ์ ๋๋ค. + +## ๐ ์ฐ๊ฒฐ๋ ์ง์ +- [[Separation_of_Concerns]] +- [[Systemic_Simulation_Principles]] diff --git a/package.json b/package.json new file mode 100644 index 00000000..45c4442e --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "tetris-game", + "version": "1.0.0", + "description": "A high-performance Tetris game using Web Workers.", + "main": "src/index.js", + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "5.0.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test" + } +} \ No newline at end of file diff --git a/src/TetrisGame.jsx b/src/TetrisGame.jsx new file mode 100644 index 00000000..e24ca092 --- /dev/null +++ b/src/TetrisGame.jsx @@ -0,0 +1,97 @@ +import React, { useState, useEffect, useCallback } from 'react'; + +const TetrisGame = () => { + // [State Management] ์ ์ญ ์ํ: ๋ณด๋์ ํ์ฌ ๋ธ๋ก ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค. + const [gameState, setGameState] = useState({ board: [], piece: null }); + const [workerStatus, setWorkerStatus] = useState("Initializing..."); + + useEffect(() => { + // 1. Web Worker ์ด๊ธฐํ ๋ฐ ํต์ ์ค์ + const worker = new Worker(new URL('./gameWorker.js', import.meta.url), { type: 'module' }); + setWorkerStatus("Running..."); + + // 2. ์์ปค๋ก๋ถํฐ ๋ฉ์์ง๋ฅผ ์์ ํ ๋ฆฌ์ค๋ ๋ฑ๋ก (Web Worker์ ํต์ฌ) + worker.onmessage = (e) => { + const data = e.data; + if (data.type === 'READY' || data.type === 'UPDATE') { + // ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ญ ์ํ๋ก ์ ๋ฐ์ดํธํฉ๋๋ค. (Single Source of Truth ์์น ์ค์) + setGameState({ board: data.board, piece: data.piece }); + } else if (data.type === 'ERROR') { + console.error("Game Worker Error:", data.message); + } + }; + + // 3. ์์ปค์ ์ด๊ธฐํ ๋ช ๋ น ์ ์ก (Worker ์์) + worker.postMessage({ type: 'INIT' }); + + // Cleanup ํจ์: ์ปดํฌ๋ํธ ์ธ๋ง์ดํธ ์ ์์ปค๋ฅผ ์ข ๋ฃํฉ๋๋ค. + return () => { + worker.terminate(); + }; + }, []); // ๋ง์ดํธ ์ ํ ๋ฒ๋ง ์คํ (useEffect) + + + // [Game Loop] ๊ฒ์ ๋ฃจํ ๊ด๋ฆฌ (ํต์ฌ ์ฑ๋ฅ ์ต์ ํ ๋ถ๋ถ) + const handleGameLoop = useCallback(() => { + if (!gameState.piece) return; + + // 1์ด์ 1๋ฒ์ฉ gravity step์ ์์ฒญํฉ๋๋ค. + const worker = new Worker(new URL('./gameWorker.js', import.meta.url), { type: 'module' }); + worker.postMessage({ type: 'MOVE_STEP', payload: {} }); + + // ๋ค์ ํ๋ ์์์ ๋ค์ ์ด ํจ์๋ฅผ ํธ์ถํ์ฌ ์ง์์ ์ธ ์์ง์์ ๋ง๋ญ๋๋ค. + requestAnimationFrame(handleGameLoop); + }, [gameState.piece]); // piece๊ฐ ์์ ๋๋ง ๋ฃจํ ์์ + + useEffect(() => { + if (gameState.piece) { + const animationFrameId = requestAnimationFrame(handleGameLoop); + return () => cancelAnimationFrame(animationFrameId); + } + }, [gameState.piece, handleGameLoop]); + + + // ๋ ๋๋ง ๋ก์ง: ๊ฒ์ ๋ณด๋์ ๋ธ๋ก์ ์๊ฐํํฉ๋๋ค. + const renderBoard = () => { + return ( +
Status: {workerStatus}
+ {renderBoard()} + +