feat: batch wiki-fication of 00_Raw data

Applied double-save rule: Master Archive + Specialized Mapping for Skybound, Datacollector, and Frontend Mastery.
This commit is contained in:
Antigravity Agent
2026-04-25 22:52:01 +09:00
parent 44f1f2140b
commit df275f935b
90 changed files with 3371 additions and 0 deletions
@@ -0,0 +1,125 @@
# Skybound Code Structure Audit and Stabilization Plan
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw analysis logged before implementation
## 1. Overview
This document records the first code-level audit after reviewing Skybound-related wiki documents. The goal was to compare the documented architecture with the actual code path in `/Volumes/Data/project/Antigravity/Skybound`, identify design and feature risks, and define the first stabilization pass.
## 2. Documents Reviewed
- `Topics/Skybound/Skybound-Knowledge-Hub.md`
- `Topics/Skybound/01_Core_Engine/Skybound-Modular-Game-Architecture.md`
- `Topics/Skybound/01_Core_Engine/Game-Engine-Loop-and-System-Orchestration.md`
- `Topics/Skybound/05_Project_Issues/2026-04-22_Engine_Stability_Audit.md`
- `Topics/Skybound/02_Combat_AI/Combat-System-and-Bullet-Interaction-Pipeline.md`
- `Topics/Skybound/04_Mechanics_Progression/Campaign_and_Dual_Loop_System.md`
- `Topics/Skybound/04_Mechanics_Progression/InGame_Progression_System.md`
- `Technical_Reports/2026-04-22_Boss_Battle_System_Implementation.md`
## 3. Code Structure Observations
Skybound's actual runtime center is `src/features/game/hooks/useGameEngine.ts`. It directly instantiates and updates `EntityManager`, `StageDirectorSystem`, `SpawnerSystem`, `CombatSystem`, `ProgressionSystem`, `ModularWeaponSystem`, `TacticalSystem`, `HazardSystem`, `BossSystem`, `EffectSystem`, and `GameRenderer`.
`SystemManager.ts` exists and documents a centralized orchestration pattern, but the active engine path does not use it. This is not inherently broken, but it creates a mismatch between the documented orchestrator and the actual execution path.
React is primarily responsible for scene composition and modal/UI handling through `GameSceneRenderer.tsx`, while Zustand state is centralized in `useGameStore.ts`.
## 4. Confirmed Problems
### 4.1 Build Gate Is Broken
`npm run build` fails. Representative causes:
- `App.tsx` imports `useGameEngine` but does not use it.
- Legacy `src/features/game/combatSystem.ts` is still included in TypeScript compilation and has type drift against current domain models.
- `useSceneAudio.ts` does not include `HANGAR` in `SCENE_AUDIO`, despite `Scene` including `HANGAR`.
- `SystemBoss.phase` is typed as `1 | 2 | 3`, while `bossRegistry.ts` contains a 4-phase boss.
- `GameRenderer.ts` calls `CanvasRenderingContext2D.close()`, which should be `closePath()`.
- `EntityManager` initializes enemies with `movePattern: 'NONE'`, which is not part of the current `Enemy.movePattern` union.
### 4.2 Timeline Spawn Intents Are Not Wired
`StageDirectorSystem` dispatches `SCRIPTED_SPAWN` and `SPAWN_MODE` intents, but `useGameEngine.ts` does not route those intents to `SpawnerSystem`.
`SpawnerSystem` already provides `notifyScriptedSpawn()` and `activateSwarmBurst()`, so the design exists but the active dispatch wiring is missing.
Expected impact: scripted waves and burst events may not appear as designed, leaving procedural spawning to carry too much of the combat pacing.
### 4.3 Campaign Stage State Is Not a Single Source of Truth
`StageDirectorSystem` receives `campaignStageIndex` when created, but `GameState.currentStage` still defaults to `1` and is not initialized from the selected campaign stage.
Expected impact: Standard campaign can show stage progression in UI while the engine continues to evaluate boss selection, damage curves, backgrounds, rewards, and tech-part rolls as Stage 1.
### 4.4 StageManager Mode Can Drift from Store Mode
`StageManager` has its own internal `mode`, defaulting to `BLITZ`. The UI updates Zustand `stageMode`, but `stageManager.setMode()` is not called from the store action.
Expected impact: Standard campaign clear can call `stageManager.onStageClear()` while the singleton still believes it is in Blitz mode, preventing next-stage campaign progression.
### 4.5 COMMS Events Are Not Rendered
`COMMS` events are emitted by engine systems, and `CommsOverlay.tsx` exists, but `useGameEngine.ts` does not map `COMMS` events to `useGameStore.setComms()`. `CommsOverlay` is also not rendered by `App.tsx`.
Expected impact: mission dialogue, warning text, and tactical pacing messages are silently dropped.
### 4.6 Starter Weapon Timer Is Not Cleaned Up
`useGameEngine.ts` starts a `setTimeout()` for starter weapon selection, but cleanup does not clear the timer.
Expected impact: if the engine unmounts quickly, a stale timer can emit a level-up modal or pause signal from an old engine instance.
### 4.7 Skill Sync Boundary Is Fragile
`GameSceneRenderer.tsx` calls store `addSkill()` and then engine `applySkill()`. `ProgressionSystem.applySkillSelection()` says Zustand owns skill increments, but also mutates `state.skills` as a fallback.
Expected impact: this usually works because of the store subscription bridge, but the ownership boundary is not clean and may cause missed or inconsistent skill levels under timing stress.
## 5. Stabilization Plan
Priority order:
1. Restore TypeScript build by removing obvious compile blockers and isolating legacy drift.
2. Wire `SCRIPTED_SPAWN` and `SPAWN_MODE` intents from `StageDirectorSystem` into `SpawnerSystem`.
3. Initialize engine `currentStage` from `stageMode` and `campaignStageIndex`.
4. Keep `StageManager` mode synchronized with Zustand `stageMode`.
5. Route `COMMS` events into the store and render `CommsOverlay`.
6. Clear the starter weapon timer during engine cleanup.
## 6. Verification Targets
- `npm run build`
- `npm run lint` as a visibility check, with the expectation that broad historical lint debt may remain after the first stabilization pass.
## 7. Implementation Result
The first stabilization pass was applied immediately after this raw audit.
### 7.1 Build Recovery
- Removed an unused `useGameEngine` import from `App.tsx`.
- Added `HANGAR` to `SCENE_AUDIO` in `useSceneAudio.ts`.
- Excluded legacy `src/features/game/combatSystem.ts` from `tsconfig.app.json` because the active runtime path uses `src/features/game/systems/CombatSystem.ts`.
- Expanded boss phase typing from `1 | 2 | 3` to `number` so 4-phase registry bosses are valid.
- Fixed `EntityManager` default enemy `movePattern` from invalid `NONE` to `SIDE_TO_SIDE`.
- Fixed `CanvasRenderingContext2D.close()` to `closePath()`.
- Removed compile-blocking unused locals from active systems.
### 7.2 Runtime Wiring Recovery
- `SCRIPTED_SPAWN` intents now call `SpawnerSystem.notifyScriptedSpawn()`.
- `SPAWN_MODE` intents now activate `SWARM_BURST` or enqueue `MINI_BOSS` spawns.
- Engine `currentStage` now initializes from `campaignStageIndex + 1` in Standard mode.
- Zustand `setStageMode()` now synchronizes the `StageManager` singleton mode.
- `COMMS` engine events now populate `useGameStore.activeComms`.
- `CommsOverlay` is rendered while playing.
- Starter weapon selection timer is cleared during engine cleanup.
### 7.3 Verification Result
- `npm run build`: passed.
- `npm run lint`: still fails due broad pre-existing lint debt, mostly `@typescript-eslint/no-explicit-any`, older helper files, and React hook lint findings. The first pass reduced the functional blockers but did not attempt a large-scale type cleanup.
@@ -0,0 +1,149 @@
# Skybound Final Stylized Casual Magitech Redirection
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw art direction correction after final concept change
## 1. Reason for Redirection
The previous pass moved Skybound toward **Semirealistic Magitech Fantasy**, but the latest direction returns the project to a clearer and more immediately readable mobile-survival style.
The new target is **Stylized Casual Magitech** for a top-down survival shooter inspired by Survivor.io.
This direction prioritizes:
- maximum in-game visibility
- bold silhouettes
- thick readable outlines
- flat lighting
- vivid magical accents
- consistent UI language from intro to mission result
## 2. Core Concept
Skybound should feel like a polished casual magitech action game rather than a dark semirealistic fantasy title.
Primary gameplay readability goals:
- player vehicle must be instantly identifiable
- enemies must remain readable in dense hordes
- pickups and weapon icons must be recognizable at small sizes
- background grid must support movement clarity without competing with combat
- every exposed screen should share the same playful magitech frame language
## 3. Tone and Manner
### Stylized Casual Magitech
Visual language:
- bold navy outlines
- clean top-down silhouettes
- flat color blocks
- minimal material noise
- bright arcane cyan
- gold/orange mechanical accents
- purple and pink enemy/corruption accents
- chunky UI frames
- high contrast buttons and progress bars
Avoid:
- gritty brushed metal
- heavy realistic shadows
- low-contrast dark UI
- thin semireal linework
- noisy texture detail
- external non-project image dependencies
## 4. Palette
Base colors:
- deep navy outline
- saturated royal blue panels
- readable sapphire floor tiles
- bright brass and gold trim
Magic accents:
- arcane cyan for player and positive energy
- crystal white-blue for highlights
- vivid purple for advanced magic
- hot pink for danger and enemy cores
- mint green for healing and positive pickups
- orange/gold for calls to action
## 5. Screen Coverage
The exposed user-facing screens were reviewed and targeted by the final theme pass:
- Intro title screen
- Airframe select screen
- Hangar / upgrade overlay
- In-game HUD
- Quick start overlay
- Tutorial overlay
- Comms overlay
- Level up modal
- Mission success / failed / complete result screen
## 6. Asset Coverage
The procedural asset generator now outputs the final Stylized Casual Magitech library while preserving runtime file paths.
Generated categories:
- Magitech player airframes
- normal enemies
- elite enemies
- bosses
- modular stage tiles
- title and result local backdrops
- item drop sprite sheet
- turret sheet
- weapon and skill icons
- projectiles
- shield and currency icons
- muzzle flash, impact, explosion, and laser VFX
- commander and pilot portraits
- contact sheet preview
## 7. Implementation Notes
The generator was redirected away from semirealistic material rendering and toward flat, readable shapes.
Main implementation choices:
- palette updated to bright casual magitech colors
- default shape helpers now draw bold navy outlines
- material texture strength reduced to keep assets flat
- background tiles use readable grid blocks and low-competition arcane circuitry
- local title and result background images were generated
- title and result screens no longer depend on external Google image URLs
- global magitech CSS override was rewritten for the final casual tone
## 8. Changed Runtime Paths
Important changed or generated paths:
- `/Volumes/Data/project/Antigravity/Skybound/scripts/generate_magitech_assets.py`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/styles/magitechArt.css`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/TitleScreen.tsx`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/ResultCard.tsx`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/magitech_art_contact_sheet.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/title_magitech.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/result_magitech.png`
## 9. Verification
Asset generation completed successfully.
Production build completed successfully with:
```bash
npm run build
```
The build still reports that `/sprites/player.png` is left unresolved at build time, which is a Vite static asset warning and was already non-blocking. The production bundle was generated successfully.
@@ -0,0 +1,74 @@
# Skybound HUD and TAC Level Up Stylized Casual Magitech Fix
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw follow-up fix from gameplay HUD screenshot review
## 1. Screenshot Issues
The reviewed gameplay screenshots showed that the HUD and TAC Level Up modal still leaned heavily into the previous cyber-terminal style.
Observed issues:
- side HUD panels used thin cyan lines and transparent glass styling
- top TAC level widget looked like a cold terminal module
- control buttons were dark monochrome blocks
- TAC Level Up modal used glitch text and blue terminal cards
- skill cards did not share the bold casual magitech frame language
## 2. Cause
The global `magitechArt.css` provided the broad art direction, but component-level CSS files still applied later or more specific styles.
Main affected files:
- `HUDOverlay.css`
- `LevelUpModal.css`
These files preserved the original Stitch/cyber UI look and overrode parts of the new tone.
## 3. Fixes Applied
### HUD
HUD styling was redirected to Stylized Casual Magitech:
- chunky navy outlines
- rounded blue magitech panels
- gold active highlights
- mint/cyan resource bars
- less transparent glass
- stronger mobile-game button affordance
- side modules grouped into readable cards
- top TAC level widget converted to a framed casual panel
### TAC Level Up Modal
The level-up modal was restyled:
- removed glitch pseudo text
- removed aggressive terminal skew animation
- converted the modal into a rounded blue magitech reward panel
- added thick dark outline and drop-shadow depth
- changed skill cards to chunky selectable cards
- changed icon boxes to framed magitech sockets
- converted level dots into brighter readable pips
- kept EVO cards gold/orange for special hierarchy
## 4. Changed Runtime Paths
Important changed paths:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HUDOverlay.css`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/LevelUpModal.css`
## 5. Verification
Production build completed successfully with:
```bash
npm run build
```
The existing `/sprites/player.png` static path warning remains non-blocking.
@@ -0,0 +1,83 @@
# Skybound Nova Burst Icon and Effect Fix
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw follow-up fix for skill-specific visual mismatch
## 1. Screenshot Issue
`Nova Burst` looked like a lemon-shaped projectile icon.
This did not match the actual skill behavior.
## 2. Skill Meaning
`Nova Burst` is not a missile, crystal shard, or thrown projectile.
Actual gameplay behavior:
- automatic radial AoE shockwave
- triggers around the player
- damages enemies inside the radius
- knocks enemies outward
- cooldown-based burst every few seconds
- evolves into `Nova Guardian`, which adds stronger golden guardian behavior
## 3. Art Direction Correction
The icon should communicate:
- central arcane core
- circular shockwave expansion
- radial force
- rune-like magitech energy
- area control around the player
It should not communicate:
- lemon
- fruit
- single projectile
- gem pickup
- missile tip
## 4. Fixes Applied
The procedural generator now creates `Nova Burst.png` with a dedicated `nova` icon shape.
New visual structure:
- cyan circular shockwave rings
- central navy magitech core
- arcane core light
- radial spokes showing outward force
- subtle purple secondary energy ring
The in-game Nova Burst renderer was also adjusted:
- center sprite is smaller and treated as a rune core
- expanding shockwave ring is now the main visual read
- added translucent pressure disk
- added segmented rune ring
- kept Guardian variant as gold/orange
## 5. Changed Runtime Paths
Important changed paths:
- `/Volumes/Data/project/Antigravity/Skybound/scripts/generate_magitech_assets.py`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/GameRenderer.ts`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/missiles/Nova Burst.png`
## 6. Verification
Asset generation completed successfully.
Production build completed successfully with:
```bash
npm run build
```
The existing `/sprites/player.png` static asset warning remains non-blocking.
@@ -0,0 +1,74 @@
# Skybound Particle and Supply Readability Fix
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw follow-up fix from gameplay screenshot review
## 1. Screenshot Issues
The reviewed screenshot exposed two readability problems.
Observed issues:
- Mint/cyan square particles were scattered across the floor and looked like items even though they could not be collected.
- The supply crate asset looked good, but it was not clear whether it was a player pickup or an enemy projectile/debris object.
## 2. Cause
### Mint Floor Squares
The mint squares were runtime particles from `EffectSystem`.
They were rendered in `GameRenderer.renderEffects()` using `fillRect()`, so every spark appeared as a small collectible-looking square.
These particles can come from combat hits, skill effects, EMP interactions, exp pickup feedback, or other short-lived feedback systems.
### Supply Ambiguity
The supply crate sprite itself was readable as an object, but the gameplay affordance was weak.
It needed explicit pickup language:
- pickup color
- capture ring
- directional marker
- short label
## 3. Fixes Applied
### Particle Shape
Runtime particles now render as small rotated diamond sparks instead of square floor blocks.
This keeps the magical spark feedback while reducing item confusion.
Normal shard fragments were also changed from square blocks to triangular fragments.
### Supply Pickup Readability
Supply drops now render with:
- mint-green dashed pickup ring
- soft pickup fill
- bobbing downward arrow
- retained supply crate sprite
- `PICK UP` label
This separates supply drops from enemy bullets, hazards, and cosmetic particles.
## 4. Changed Runtime Paths
Important changed path:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/GameRenderer.ts`
## 5. Verification
Production build completed successfully with:
```bash
npm run build
```
The existing `/sprites/player.png` static path warning remains non-blocking.
@@ -0,0 +1,141 @@
# Skybound Semirealistic Magitech Fantasy Redirection
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw art direction correction before second asset pass
## 1. Reason for Redirection
The first generated art pack leaned too far into childish cartoon readability: thick outlines, flat toy-like shapes, and simplified symbolic silhouettes.
The new target is **Semirealistic Magitech Fantasy** for a top-down horde survival-shmup inspired by Survivor.io, aimed at players aged 12-18 and casual adults.
## 2. Core Concept
The visual library should feel detailed, grounded, and cool rather than cute.
Primary references by feel:
- League of Legends-like readable fantasy detail
- Warhammer-like dark material weight
- Survivor.io-like top-down clarity and grid readability
This is still a game with high enemy density, so readability remains critical, but contrast should come from lighting, value, and energy color rather than thick black outlines.
## 3. Tone and Manner
### Semirealistic Magitech
Visual language:
- dark iron
- aged brass
- brushed metal
- weathered stone
- glowing crystals
- engraved runes
- arcane circuitry
- controlled deep shadows
- focused magical highlights
Avoid:
- childish cartoon shapes
- toy-like flat icons
- heavy black outlines
- overly bright candy palettes
- large simplified emblem-only designs
## 4. Palette
Base colors:
- dark sapphire
- dark iron
- forest green
- weathered brass
- basalt gray
- deep crimson
Magic accents:
- arcane blue for player energy
- neon purple for corruption
- plasma red for enemy/boss danger
- molten orange for forge/lava accents
## 5. Asset Rules
### Player Vehicle
The player vehicle should read as a Magitech airship rather than a simple airplane.
Required traits:
- complex symmetrical or slightly asymmetrical hull
- dark iron and brass material mix
- intense crystalline power core
- smaller gun turrets
- visible engine components, gears, vents, and rune plates
- subtle energy glow readable from top-down view
### Enemies
Enemies should be threatening corrupted creatures or ancient mechanical horrors.
Examples:
- clockwork spiders with poison sacks
- rune golems made of dark stone
- corrupted winged drakes
- ancient mechanical horrors with plasma-red cores
### Background
Background should preserve Survivor.io-style grid readability but feel like an immersive fantasy environment.
Target environments:
- ancient overgrown Magitech city ruin
- subterranean magma forge
Rules:
- weathered stone pavement
- broken magitech circuitry embedded in the floor
- basalt structures
- subtle lava or arcane channels
- background contrast lower than enemies and player
### Effects
Player effects should be arcane blue or crystal cyan.
Enemy effects should lean plasma red, purple, or corrupted crimson.
Death effects should be optimized and satisfying:
- scrap metal shards
- dark crystal fragments
- arcane dust
- controlled flashes, not full-screen clutter
### UI
UI should use Survivor.io-like directness with a refined dark iron and crystal shell.
Required traits:
- heavy dark iron frames
- crystal level bar
- rune and gear details
- minimal but detailed HUD
- clean modern gothic / steampunk-inspired readability
## 6. Implementation Notes
The next pass should replace the first cartoony art pack with a darker semirealistic procedural raster set while preserving runtime file paths.
The existing generator should be rewritten so future iterations can adjust palette, materials, and silhouettes consistently.
@@ -0,0 +1,153 @@
# Skybound Semirealistic Magitech Fantasy Art Pack
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Superseded by semirealistic second pass
## 1. Direction
Skybound's 2D visual identity was first redirected toward **Stylized Casual Magitech**, then corrected into **Semirealistic Magitech Fantasy** after visual review.
The corrected target tone is a top-down survival shooter inspired by clear mobile action readability, but with more mature fantasy material treatment:
- reduced outlines
- dark iron and brass material language
- controlled lighting
- glowing crystalline cores
- corrupted magical enemies
- ancient magitech ruin backgrounds
- high contrast at small gameplay sizes
- color-coded enemy and weapon readability
- playful magitech forms instead of realistic military hardware
## 2. Core Art Rules
### Silhouette
Every gameplay object must remain readable at 36-72px on canvas.
- Player vehicles use triangular forward-facing silhouettes.
- Normal enemies use compact diamond/bug-like silhouettes.
- Elite enemies use wider, more decorated silhouettes.
- Bosses use tall central hulls with visible side modules and glowing cores.
- Weapons and drops use symbolic icons instead of detailed illustrations.
### Linework
Use value contrast and glow separation instead of heavy cartoon outlines.
Purpose:
- separates sprites from busy scrolling backgrounds through lighting
- keeps bullets, drops, and enemies visible during VFX-heavy combat
- supports a grounded semirealistic style
### Lighting
Lighting is controlled and directional. Avoid noisy photorealism, but use subtle brushed metal, stone, and crystal texture.
Allowed:
- small inner highlights
- soft magical glow behind important objects
- subtle bevels
- material grain
- controlled shadow
Avoid:
- toy-like flat panels
- low-contrast smoke
- tiny greeble details
### Palette
Corrected palette:
- Void: `#080a12`
- Dark iron: `#1c2029`
- Aged brass: `#a57a37`
- Dark sapphire: `#102a52`
- Forest green: `#164535`
- Crimson: `#671a20`
- Arcane blue: `#36cdff`
- Neon purple: `#b03eff`
- Plasma red: `#ff4149`
- Molten orange: `#ff7a21`
## 3. Generated Asset Coverage
The following runtime assets were regenerated in-place under `public/sprites`:
- player airframes: `Falcon.png`, `rayce.png`
- charge shot: `chargeshot.png`
- normal enemies: `normal_enemy/enemy01.png` through `enemy09.png`
- elite enemies: `elite_enemy/elite01.png` through `elite16.png`
- bosses: `boss/tile000.png` through `tile010.png`
- turret atlas: `turret/turret_sprites.png`
- item drops: `item_drops_sprite.png`
- stage backgrounds: `background/stage_tile_1.png` through `stage_tile_8.png`
- weapon and skill icons under `sprites/missiles`
- core bullet, shield, currency, VFX sprites
- comms portraits: `portraits/hq_commander.png`, `portraits/pilot_standard.png`
## 4. UI Skin Coverage
The UI skin was added through:
- `src/features/game/styles/magitechArt.css`
- imported from `src/App.css`
The skin aligns:
- HUD panels
- level-up cards
- comms overlay
- hangar/action buttons
- warning text
- canvas saturation/contrast
## 5. Generator
The art pack is reproducible through:
`scripts/generate_magitech_assets.py`
This script uses the bundled Python runtime with Pillow and generates vector-like raster PNGs. It intentionally avoids relying on one-off manual image files so future palette or silhouette changes can be regenerated consistently.
## 6. Preview Sheet
Generated preview sheet:
`public/sprites/magitech_art_contact_sheet.png`
The preview sheet is for art review only and is not currently consumed by the game runtime.
## 7. Follow-up Art Tasks
Recommended next art pass:
1. Add animation frame variants for normal and elite enemies.
2. Split skill icons into a formal UI icon atlas instead of relying on individual PNGs.
3. Add boss-specific silhouettes matching the narrative names in `bossRegistry.ts`.
4. Add projectile color language documentation for player, enemy, boss, and gimmick bullets.
5. Replace remaining CSS vocabulary from older cyber-neon UI with magitech naming over time.
## 8. Second Pass Correction
After user review, the first art pack was judged too childish/cartoon-like. The generator and UI skin were rewritten.
Second pass changes:
- removed thick outlines
- added brushed metal / stone noise
- added stronger shadows and glow-based separation
- changed vehicles into darker magitech airships
- changed enemies into corrupted mechanical/stone silhouettes
- changed backgrounds into darker stone grid ruins with broken circuitry
- changed UI from bright toy-card framing to dark iron/crystal framing
The reproducible generator remains:
`scripts/generate_magitech_assets.py`
@@ -0,0 +1,102 @@
# Skybound Stylized Casual Magitech Ingame Asset Fix
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw follow-up fix from gameplay screenshot review
## 1. Screenshot Issues
The reviewed screenshots exposed three in-game visual problems.
Observed issues:
- `SUPPLY` air drop was rendered as a simple cyan ring and text label instead of a proper magitech supply crate.
- Enemy sprites showed a faint rectangular transparency box around the aircraft body.
- Large falling translucent circular hazards were rendered as plain gray circles and did not match the Stylized Casual Magitech tone.
## 2. Cause
### Supply Drop
The supply drop was not using an image asset.
It was drawn directly in `GameRenderer.renderAirDrops()` as:
- animated circle stroke
- translucent cyan fill
- white `SUPPLY` text
### Enemy Rectangle Artifact
The procedural generator used glow layers and Lanczos downsampling.
This left very low alpha pixels across the image canvas. In gameplay, those tiny alpha values became visible as a faint rectangular box around enemies.
### Falling Circular Hazard
The falling translucent circle was an `EMP_CLOUD` hazard.
It was drawn directly in `GameRenderer.renderHazards()` as a generic gray filled circle.
## 3. Fixes Applied
### Supply Drop Asset
A new stylized magitech crate sprite was generated:
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/supply_crate.png`
The renderer now draws this crate for air drops while preserving a small dashed cyan capture ring.
### Alpha Cleanup
The procedural asset generator now clamps very low alpha values to `0` during PNG export.
This removes transparent rectangle artifacts while keeping intended outlines, glow, and silhouettes.
Verified enemy sprite alpha:
- normal enemy corner alpha: `0`
- elite enemy corner alpha: `0`
- boss corner alpha: `0`
- no alpha values below the cleanup threshold remain
### Hazard Assets
New hazard sprites were generated:
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_emp.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_asteroid.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_debris.png`
`EMP_CLOUD` now renders as an arcane rune-field instead of a plain gray circle.
`ASTEROID` and `DEBRIS` can render as stylized magitech rock fragments instead of fallback circles.
## 4. Changed Runtime Paths
Important changed or generated paths:
- `/Volumes/Data/project/Antigravity/Skybound/scripts/generate_magitech_assets.py`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameAssets.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/GameRenderer.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/utils/SpriteUtils.ts`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/supply_crate.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_emp.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_asteroid.png`
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/vfx/vfx_hazard_debris.png`
## 5. Verification
Asset generation completed successfully.
Alpha inspection confirmed transparent corners and no low-alpha rectangle residue for the checked enemy/boss/supply/hazard sprites.
Production build completed successfully with:
```bash
npm run build
```
The build still reports the existing `/sprites/player.png` static path warning, but it remains non-blocking and the production bundle was generated successfully.
@@ -0,0 +1,177 @@
# Skybound Survivor-Like Balance Curve Pass
**Date**: 2026-04-24
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw gameplay balance pass from user playtest feedback
## 1. Playtest Feedback
The game shell looked close to Survivor.io / Vampire Survivors, but the actual gameplay did not feel like that genre.
Reported issues:
- gameplay did not deliver enough horde-survival pressure
- stage balance felt uneven
- TAC Level Up pacing felt unbalanced
- growth did not form a satisfying user-facing curve
## 2. Diagnosis
The previous balance leaned closer to a shmup / tactical shooter.
Main causes found in code:
- simultaneous enemy cap was too low for a horde-survival feel
- procedural spawn did not fully use the timeline `spawnIntervalMult`
- early EXP requirement was too high
- EXP growth multiplier was too steep
- stage difficulty scaled enemy/bullet stats too aggressively
- stage scripted events were compressed too early in the timeline
- TAC Level Up card offers were weighted but not structured, so the user could receive awkward choices
- starter skill offers could omit key horde-survival archetypes
## 3. Target Curve
New target:
- first meaningful upgrade should arrive quickly
- player should see more enemies on screen
- enemies should be individually weaker
- danger should come from density and positioning, not bullet stat spikes
- level-up choices should consistently support build formation
- stage progression should rise smoothly rather than jump sharply
## 4. Applied Balance Changes
### EXP and Level-Up
Changes:
- initial required EXP lowered from `100` to `45`
- normal enemy EXP increased from `5` to `7`
- elite EXP increased from `25` to `32`
- level-up EXP multiplier changed from steep `1.60 / 1.72 / 1.85` to smoother `1.24 / 1.30 / 1.36 / 1.42`
Expected result:
- early TAC Level Ups arrive faster
- the player can form a build before the first spike
- later progression still slows down without becoming a wall
### TAC Level Up Card Structure
The card generator now tries to offer:
- one owned skill upgrade
- one synergy / spike-counter / EVO-supporting option
- one flexible option
Expected result:
- fewer dead-choice screens
- higher chance of completing coherent builds
- less frustration from random-only card pools
### Starter Selection
Starter cards now come from three archetype buckets:
- primary damage
- area / crowd control
- utility / defense
Expected result:
- every run begins with a usable horde-survival foundation
- the first choice feels strategic without becoming punishing
### Enemy Density and Spawning
Changes:
- hard enemy cap increased from `30` to `90`
- timeline phase caps increased by stage and phase
- procedural spawn interval now uses `spawnIntervalMult`
- procedural spawns can arrive in small batches
- formation spawns now occur more often
- individual enemy HP and speed were reduced to support higher density
- elite chance is now a gradual probability instead of flipping too hard by difficulty
Expected result:
- more screen-filling horde pressure
- less empty movement time
- more satisfying weapon-clearing moments
### Stage Curve
Changes:
- stage duration curve changed from `120 + stage * 30s` to `150 + stage * 18s`
- stage difficulty scaling reduced from steep `+0.4 per stage` to smoother `+0.18 per stage`
- phase difficulty multipliers were lowered
- phase enemy caps were increased
- scripted wave events are distributed across the stage instead of firing too early
Expected result:
- stages feel less spiky and more readable
- difficulty rises through density and phase rhythm
- player has time to grow before major pressure events
### Enemy Bullet and Damage Pressure
Changes:
- enemy bullet speed curves were reduced
- damage curves were reduced
- bullet caps were reduced
- global enemy bullet speed multiplier reduced
- enemy projectile damage multipliers reduced
Expected result:
- gameplay moves away from bullet-hell punishment
- movement pressure still exists, but horde positioning becomes the main focus
### Weapon Rhythm
Several weapon cooldowns were shortened so early picks feel active sooner.
Nova Burst was also adjusted to trigger sooner and scale more clearly as an AoE crowd-control tool.
## 5. Changed Runtime Paths
Important changed paths:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/balance.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/CombatTimeline.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/weaponBehaviors.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/SpawnerSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ProgressionSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/CombatSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ModularWeaponSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/types.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameEngine.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/store/useGameStore.ts`
## 6. Verification
Production build completed successfully with:
```bash
npm run build
```
The existing `/sprites/player.png` static path warning remains non-blocking.
## 7. Next Playtest Questions
Recommended next playtest checks:
- Does the first level-up happen within a satisfying time window?
- Does the screen feel populated without becoming unreadable?
- Do weapons feel like they clear hordes?
- Do stage spikes feel earned rather than sudden?
- Does TAC Level Up usually offer at least one desirable choice?
@@ -0,0 +1,60 @@
# Datacollector - 인증 복구 후 자동 재개 상태 전환 수정
- 작성 시각: 2026-04-25 22:39:30 KST
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
- 관련 파일: `src/components/AgentDashboard.tsx`, `src/lib/engine.ts`
## 상황
NotebookLM 인증 복구 로직을 강화했지만, 화면에서는 여전히 `CONTINUE MISSION` 버튼을 사용자가 눌러야 다음 큐가 이어지는 것처럼 보였다.
사용자 관찰:
- 작업은 일부 완료됨.
- 큐에는 아직 작업이 많이 남아 있음.
- 헤더 상태가 `IDLE`로 보임.
- `CONTINUE MISSION` 버튼이 사용자의 수동 클릭을 기다림.
## 원인
프론트엔드 상태 전환에 빈틈이 있었다.
`AgentDashboard``useEffect``status !== 'running'`일 때 `KnowledgeEngine.stop()`을 호출한다. 그런데 기존 `stop()`은 내부 실행 플래그만 끄는 것이 아니라 항상 Zustand 상태까지 `idle`로 바꿨다.
그 결과 인증 오류 등으로 `paused` 상태를 유지해야 하는 경우에도 React effect를 지나면서 `paused -> idle`로 바뀌었다. 이렇게 되면 앱은 "복구 후 자동 재개 가능한 일시정지"가 아니라 "사용자가 다시 Continue를 눌러야 하는 대기 상태"처럼 동작했다.
## 조치
`src/lib/engine.ts`:
- `stop(updateStatus = true)` 형태로 변경했다.
- 내부 엔진만 멈춰야 할 때는 UI 상태를 덮어쓰지 않도록 했다.
`src/components/AgentDashboard.tsx`:
- `status !== 'running'` effect에서는 `engine.stop(false)`를 호출하도록 변경했다.
- `status === 'paused'`이고 큐가 남아 있으면 NotebookLM 연결 확인 후 자동으로 `running`으로 되돌리는 auto-resume effect를 추가했다.
- 기존 버그로 이미 `idle`에 갇힌 화면도 구제하기 위해, 수동 정지나 작업 완료 로그가 없는 `idle + 남은 큐` 상태도 복구 가능한 멈춤으로 보고 자동 재개하도록 보강했다.
- 중복 자동 재개를 막기 위해 `autoResumeRef` 잠금을 추가했다.
## 검증
다음 검증을 완료했다.
```bash
npm run lint
curl -sS -I http://127.0.0.1:3000
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
```
결과:
- TypeScript 검사 통과
- 프론트엔드 서버 응답 정상
- NotebookLM 브리지 연결 확인 `success: true`
## 운영 메모
앞으로 인증 복구나 연결 복구로 인해 `paused` 상태가 되면 앱이 NotebookLM 연결을 확인하고 자동으로 다음 큐를 이어서 실행한다.
사용자가 직접 `STOP / PAUSE`를 누른 경우는 기존처럼 `idle`로 유지되므로, 수동 정지는 자동 재개 대상이 아니다.
@@ -0,0 +1,72 @@
# Datacollector Bridge Connection Refused Run Script Fix
Date: 2026-04-25 21:07:52 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
사용자가 앱 실행 후 `POST http://127.0.0.1:3002/api/check-connection net::ERR_CONNECTION_REFUSED` 오류를 확인했다.
이는 NotebookLM 인증 실패가 아니라 MCP Bridge 서버가 실행되지 않아 브라우저가 `3002` 포트에 연결하지 못한 상태였다.
## Root Cause
실행 경로가 여러 개였고 일부 경로는 프런트엔드 Vite 서버만 실행했다.
- `run_mac.command`: Bridge와 Vite를 함께 실행
- `run_app.sh`: Vite만 실행
- `npm run dev`: Vite만 실행
따라서 `run_app.sh` 또는 `npm run dev`로 앱을 켜면 UI는 열리지만 `/api/check-connection` 요청을 받을 Bridge 서버가 없어 `ERR_CONNECTION_REFUSED`가 발생했다.
## Changes Made
수정 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/run_app.sh`
- `/Volumes/Data/project/Antigravity/Datacollector/README.md`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/api.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
핵심 변경:
- `run_app.sh`가 Bridge 서버와 Vite 서버를 함께 실행하도록 변경
- `run_app.sh` 시작 시 기존 `3000`, `3002` 포트 프로세스를 정리
- 종료 시 Bridge 백그라운드 프로세스도 함께 종료하도록 trap 추가
- README의 실행 안내를 `npm run dev` 단독에서 `./run_mac.command` 또는 `npm run start-full`로 변경
- `src/lib/api.ts``bridgeFetch()` 추가
- Bridge 연결 실패 시 `Failed to fetch` 대신 “Bridge 서버가 실행되지 않았다”는 안내 메시지를 표시하도록 변경
- `VITE_BRIDGE_URL`로 Bridge 주소를 override할 수 있게 함
## Verification
실행한 검증:
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
npm run build
```
검증 결과:
- 브리지 문법 체크 통과
- TypeScript 타입체크 통과
- Vite 프로덕션 빌드 통과
## Operational Note
앞으로 앱은 아래 방식으로 실행해야 한다.
```bash
./run_mac.command
```
또는 수동으로 두 서버를 같이 실행한다.
```bash
npm run start-full
```
`npm run dev`만 실행하면 프런트엔드만 뜨므로 NotebookLM, Wiki save, 인증 복구 API가 동작하지 않는다.
@@ -0,0 +1,177 @@
# Datacollector Codebase Structure Review and Initial Risk Assessment
Date: 2026-04-25 20:38:01 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
Knowledge Vault: `/Volumes/Data/project/Antigravity/Wiki/00_Raw`
## Summary
이 문서는 Datacollector 프로젝트의 첫 구조 파악 및 초기 코드 리뷰 결과를 정리한 기록이다.
이번 검토의 목적은 이후 기능 개발 전에 현재 시스템의 책임 분리, 실행 흐름, 외부 의존성, 그리고 우선적으로 손봐야 할 위험 요소를 이해하는 데 있다.
현재 프로젝트는 단순한 프런트엔드 앱이 아니라, React 기반 UI와 Zustand 상태 저장소, 자율 실행 엔진, 그리고 NotebookLM MCP 및 로컬 LM을 연결하는 Express 브리지 서버가 결합된 자동화 연구 도구 형태로 구성되어 있다.
## High-Level Architecture
전체 흐름은 아래와 같다.
`React UI -> Zustand Store -> KnowledgeEngine -> Express Bridge -> NotebookLM MCP / Local LM / GitHub / Wiki Storage`
핵심 책임 분리는 다음과 같이 이해했다.
- `src/components/AgentDashboard.tsx`
사용자 인터페이스, 미션 시작/중지/재개, 설정 입력, 로그 표시, 수동 커밋 등 상호작용 담당
- `src/store/agentStore.ts`
앱 전체 설정값과 실행 상태를 보관하는 단일 전역 상태 저장소
- `src/lib/engine.ts`
큐를 소비하며 연구, 합성, 링크 추출, 다음 토픽 확장을 반복하는 자율 엔진
- `src/lib/gemini.ts`
NotebookLM 미연결 시 사용하는 로컬 LM 프롬프트 생성 및 응답 파싱
- `src/lib/github.ts`
결과 Markdown을 GitHub 저장소의 `00_Raw/` 경로로 업로드
- `scripts/mcp_bridge.mjs`
NotebookLM MCP 서버와 통신하는 지속 프로세스형 브리지 서버
## Execution Flow
실행 흐름은 다음 순서로 이해했다.
1. 사용자가 `AgentDashboard`에서 주제를 입력하고 미션을 시작한다.
2. 주제와 설정이 `agentStore`에 기록되고 상태가 `running`으로 바뀐다.
3. `status` 변경을 감지한 UI가 `KnowledgeEngine` 싱글톤을 시작한다.
4. `KnowledgeEngine`는 큐의 첫 항목을 읽고 현재 깊이와 루트 주제를 기준으로 처리 여부를 결정한다.
5. NotebookLM 연결 상태가 좋으면 브리지 서버를 통해 리서치와 합성을 수행한다.
6. NotebookLM이 없으면 로컬 LM 프록시(`/api/lm`)를 통해 대체 연구를 진행한다.
7. 생성된 Markdown에서 위키 링크를 추출해 다음 큐를 구성한다.
8. 결과는 pending commits, completed 목록, 로컬 위키 Raw 저장소 등에 반영된다.
## Current Structure Notes
이번 시점에서 구조적으로 눈에 띈 특징은 다음과 같다.
- 상태 관리가 거의 전부 Zustand store 하나에 집중되어 있어 흐름 추적은 쉽다.
- 대신 엔진과 UI가 store를 매우 직접적으로 공유해서 결합도가 높다.
- NotebookLM 경로와 Local LM 경로가 모두 존재해 fallback 전략은 분명하다.
- 브리지 서버가 프런트엔드 백엔드이자 외부 도구 래퍼 역할까지 함께 맡고 있어 책임이 넓다.
- 문서 저장 흐름이 GitHub 업로드와 로컬 위키 저장으로 이중화되어 있다.
## Review Findings
### 1. Sensitive secrets are persisted in browser storage
`githubToken``notebookLmCookies`가 Zustand persist 설정에 포함되어 있어 브라우저 localStorage에 평문으로 저장된다.
이 방식은 세션 쿠키나 GitHub 토큰 같은 민감 정보의 저장 위치로는 안전하지 않다.
관련 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
영향:
- 같은 브라우저 프로필을 사용하는 다른 코드나 도구가 정보에 접근할 수 있다.
- 장기적으로 토큰 유출 위험이 커진다.
### 2. Bridge server is exposed too broadly
브리지 서버는 `0.0.0.0:3002`로 열리고 CORS도 전부 허용한다.
또한 `/api/lm`은 클라이언트가 전달한 임의의 URL로 요청을 프록시할 수 있다.
관련 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
영향:
- 로컬 개발용으로는 편하지만, 같은 네트워크 안에서 예상하지 않은 접근 통로가 될 수 있다.
- 사실상 무인증 프록시처럼 동작할 여지가 있다.
### 3. Environment portability is weak
MCP 실행 파일 경로와 위키 저장 경로가 절대경로로 하드코딩되어 있다.
관련 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
영향:
- 다른 개발자 머신, 다른 사용자 계정, 다른 운영체제에서 그대로 실행하기 어렵다.
- 배포보다는 특정 개인 작업 환경에 강하게 종속된다.
### 4. Manual handoff state is not fully cleared
`resolveManualNext`가 store에 함수 형태로 저장되는데, `clearState()`에서 정리되지 않는다.
수동 합성 대기 중 reset 또는 새 미션 시작이 발생하면 상태 꼬임 가능성이 있다.
관련 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
영향:
- 이전 미션의 대기 상태가 다음 미션에 잔존할 수 있다.
- UI 버튼 상태와 실제 엔진 대기 상태가 어긋날 수 있다.
### 5. API endpoint usage is duplicated and hardcoded
프런트엔드에는 이미 Vite 프록시가 설정되어 있지만, UI와 엔진 코드 곳곳에서 `http://127.0.0.1:3002`를 직접 호출하고 있다.
관련 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/vite.config.ts`
영향:
- 포트 변경이나 배포 환경 변경 시 수정 지점이 늘어난다.
- 런타임 경로 설정이 한 군데에서 관리되지 않는다.
## Validation Performed
이번 검토 중 아래 확인을 수행했다.
- 저장소 파일 구조 및 진입점 확인
- UI, store, engine, bridge, GitHub, Local LM 계층 코드 확인
- `npm run lint` 실행
검증 결과:
- TypeScript 타입체크는 현재 통과했다.
## Suggested Next Priorities
우선순위는 아래 순서가 적절하다.
1. 민감 정보 저장 방식을 localStorage 바깥으로 이동하거나 최소한 분리
2. 브리지 서버 바인딩 범위와 CORS 정책 축소
3. 절대경로를 환경변수 또는 설정 파일로 치환
4. `resolveManualNext`를 포함한 미션 종료 정리 로직 강화
5. API 베이스 URL을 단일 설정 지점으로 통합
## Working Agreement For Future Notes
사용자 요청에 따라, 앞으로 Datacollector 관련 조사/분석/리뷰 결과는 가능하면 이 지식 창고 경로에 계속 기록한다.
기본 원칙:
- 위치: `/Volumes/Data/project/Antigravity/Wiki/00_Raw`
- 파일명: `YYYY-MM-DD-<Project>_<Topic>.md` 또는 기존 저장소 관례와 유사한 읽기 쉬운 영어 제목
- 내용: 작업 목적, 파악한 구조, 핵심 발견사항, 다음 액션을 포함
## Source Files Reviewed
- `/Volumes/Data/project/Antigravity/Datacollector/README.md`
- `/Volumes/Data/project/Antigravity/Datacollector/package.json`
- `/Volumes/Data/project/Antigravity/Datacollector/vite.config.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/main.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/src/App.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/gemini.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/github.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_caller.py`
@@ -0,0 +1,74 @@
# Datacollector Local Wiki Save Only Output Mode
Date: 2026-04-25 20:50:41 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
Datacollector의 생성 결과 저장 방식을 GitHub 업로드 중심에서 로컬 Wiki 저장 전용으로 정리했다.
앞으로 앱에서 생성되는 연구 문서는 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`에 저장되고, Git 업로드는 사용자가 나중에 별도로 한 번에 처리하는 운영 방식으로 둔다.
## Previous Behavior
기존 흐름은 결과 생성 후 두 경로가 동시에 존재했다.
- 로컬 Wiki Raw 폴더에 자동 저장
- `pendingCommits`에 결과를 쌓고 UI의 `BATCH COMMIT` 버튼으로 GitHub 업로드 가능
이 방식은 앱 안에 GitHub 토큰과 저장소 설정을 유지해야 했고, 사용자가 의도하지 않아도 Git 업로드 기능이 계속 노출되는 구조였다.
## New Behavior
새 흐름은 다음과 같다.
1. 연구 결과 Markdown 생성
2. `savedReports`에 프리뷰용 로컬 캐시 저장
3. 브리지 서버의 `/api/wiki/save`를 통해 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`에 Markdown 파일 저장
4. GitHub 업로드 버튼이나 토큰 설정 없이 완료
GitHub 업로드는 앱이 수행하지 않는다.
## Changes Made
수정 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/src/store/agentStore.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/engine.ts`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/.env.example`
삭제 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/src/lib/github.ts`
핵심 변경:
- `githubToken`, `githubRepoUrl` 상태 제거
- `pendingCommits` 제거
- `addPendingCommit`, `clearPendingCommits` 제거
- `savedReports``addSavedReport` 추가
- `BATCH COMMIT` 버튼 제거
- 설정 모달의 GitHub Wiki Sync 섹션 제거
- `.env.example`의 GitHub 설정 제거
- 생성 결과는 기존 Wiki 저장 API를 통해 로컬 Raw 폴더에만 저장
## Verification
실행한 검증:
```bash
npm run lint
npm run build
```
검증 결과:
- TypeScript 타입체크 통과
- Vite 프로덕션 빌드 통과
## Notes
로컬 Wiki 저장은 기존 브리지 서버의 `/api/wiki/save` 라우트를 그대로 사용한다.
저장 대상 경로는 현재 브리지 서버에 하드코딩된 `/Volumes/Data/project/Antigravity/Wiki/00_Raw`이다.
추후 이 경로도 `.env` 설정으로 분리하면 다른 머신이나 폴더 구조에서도 더 쉽게 운영할 수 있다.
@@ -0,0 +1,50 @@
# Datacollector Mac Windows Launcher Scripts
Date: 2026-04-25 21:09:42 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
Datacollector 실행 시 Vite 프런트엔드만 뜨고 MCP Bridge 서버가 뜨지 않아 `ERR_CONNECTION_REFUSED`가 발생할 수 있었다.
이를 막기 위해 맥용과 윈도우용 실행 파일을 명확히 정리했다.
## Main Launchers
- macOS: `/Volumes/Data/project/Antigravity/Datacollector/run_mac.command`
- Windows: `/Volumes/Data/project/Antigravity/Datacollector/run_win.bat`
두 실행 파일 모두 아래를 수행한다.
1. 프로젝트 폴더로 이동
2. `node_modules`가 없으면 `npm install`
3. 기존 `3000`, `3002` 포트 프로세스 정리
4. MCP Bridge 서버 실행
5. Vite 앱 실행
## Compatibility Wrappers
기존 실행 파일과의 호환성을 위해 아래 파일은 메인 실행 파일로 위임하도록 단순화했다.
- `run_app.sh` -> `run_mac.command`
- `run_app.bat` -> `run_win.bat`
## Verification
실행한 검증:
```bash
bash -n run_mac.command
bash -n run_app.sh
npm run lint
```
검증 결과:
- macOS shell script 문법 통과
- TypeScript 타입체크 통과
## Operational Note
앞으로 맥에서는 `run_mac.command`, 윈도우에서는 `run_win.bat`만 실행하면 된다.
`npm run dev` 단독 실행은 프런트엔드만 켜므로 NotebookLM, Wiki save, 인증 복구 API가 동작하지 않는다.
@@ -0,0 +1,68 @@
# Datacollector - NotebookLM 인증 브라우저 유지 및 오래된 .env 쿠키 우선순위 문제 해결
- 작성 시각: 2026-04-25 21:31:00 KST
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
- 관련 파일: `scripts/mcp_bridge.mjs`, `auth_mac.command`, `auth_win.bat`, `.env.example`
## 상황
앱에서 `/api/check-connection` 호출이 500으로 실패했고, 화면에는 다음과 같은 메시지가 반복되었다.
- `Authentication expired`
- `인증 자동 복구 실패. 브라우저 로그인이 필요한 상태일 수 있습니다.`
- `MCP initialized: true, pending: 0`
사용자는 NotebookLM 인증 중 Chrome이 열렸다가 닫히는 점을 보고, 인증 브라우저를 유지해야 하는 것 아니냐고 질문했다.
## 확인한 내용
`notebooklm-mcp-auth` 소스 확인 결과, 기본 자동 실행 모드는 인증 후 자신이 띄운 Chrome 프로세스를 종료한다. 반면 `--no-auto-launch --port ... --user-data-dir ...` 모드는 이미 떠 있는 Chrome 디버깅 세션에 붙기 때문에 인증 브라우저를 유지할 수 있다.
브리지에서 Chrome을 유지하도록 바꾼 뒤 인증 CLI는 성공했다. 하지만 MCP 서버의 `notebook_list`는 여전히 `Authentication expired`를 반환했다.
추가 확인 결과, `.env`에 예전 `NOTEBOOKLM_COOKIES` 값이 남아 있었다. `scripts/mcp_bridge.mjs``dotenv/config`를 로드한 뒤 MCP 서버를 자식 프로세스로 실행하면서 이 오래된 환경변수 쿠키가 `~/.notebooklm-mcp/auth.json`의 최신 인증 캐시보다 우선 적용되고 있었다.
즉 실제 핵심 원인은 다음 조합이었다.
- 인증 CLI는 최신 쿠키를 `~/.notebooklm-mcp/auth.json`에 정상 저장함.
- 브리지는 `.env`의 오래된 `NOTEBOOKLM_COOKIES`를 MCP 자식 프로세스에 전달함.
- MCP 서버는 캐시 파일보다 환경변수를 우선 사용함.
- 결과적으로 새 인증 후에도 MCP는 계속 오래된 쿠키로 NotebookLM API를 호출함.
## 조치
`scripts/mcp_bridge.mjs`에서 기본적으로 MCP 자식 프로세스와 인증 CLI 자식 프로세스에 `NOTEBOOKLM_COOKIES`, `NOTEBOOKLM_CSRF_TOKEN`, `NOTEBOOKLM_SESSION_ID`를 넘기지 않도록 수정했다.
명시적으로 환경변수 인증을 사용해야 할 경우에는 `.env`에 아래 값을 둔다.
```env
USE_NOTEBOOKLM_ENV_AUTH="true"
```
기본값은 `false`이며, 이 경우 `notebooklm-mcp-auth`가 생성한 `~/.notebooklm-mcp/auth.json` 캐시를 우선 사용한다.
또한 `auth_mac.command`, `auth_win.bat`는 별도 Chrome 프로필과 디버깅 포트를 사용해 NotebookLM 인증 브라우저를 열어두는 방식으로 변경했다.
## 검증
다음 검증을 완료했다.
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
```
결과:
```json
{"success":true,"count":0}
```
직접 Python MCP 클라이언트로도 같은 인증 캐시를 사용해 `list_notebooks` 호출이 성공했고, 노트북 89개를 읽는 것을 확인했다.
## 운영 메모
앞으로는 `.env`에 오래된 `NOTEBOOKLM_COOKIES`가 남아 있어도 기본 브리지 실행에는 영향을 주지 않는다. 다만 혼란을 줄이려면 장기적으로 `.env`에서 `NOTEBOOKLM_COOKIES` 줄을 삭제하거나 주석 처리하는 것이 좋다.
NotebookLM 인증용 Chrome 창은 닫지 않는 것이 좋다. 인증이 풀렸을 때 브리지가 같은 디버깅 포트의 Chrome 세션에 붙어 자동 복구를 시도할 수 있다.
@@ -0,0 +1,85 @@
# Datacollector NotebookLM Automatic Auth Recovery
Date: 2026-04-25 20:47:05 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
컴퓨터 포맷 이후 NotebookLM MCP 인증이 자주 실패하고, 20-30분마다 `auth_mac.command`를 수동 실행해야 하는 문제가 있었다.
이번 작업에서는 인증 만료 시 브리지 서버가 자동으로 복구를 시도하도록 개선했다.
## Root Cause Hypothesis
기존 구조는 MCP 서버의 `refresh_auth` 도구 호출에만 의존했다.
하지만 포맷 이후 로컬 토큰 저장 위치나 Chrome 세션 상태가 달라지면서 `refresh_auth`만으로 복구되지 않는 상황이 발생할 수 있다.
사용자가 직접 실행하던 파일은 다음 명령의 래퍼였다.
```bash
/Users/g1nation_mac/.local/bin/notebooklm-mcp-auth
```
따라서 자동 복구 흐름에도 이 CLI 인증 명령을 포함시키는 것이 가장 직접적인 개선 방향이다.
## Changes Made
수정 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/.env.example`
핵심 변경:
- 브리지 서버가 `.env`를 읽도록 `dotenv/config`를 추가했다.
- `AUTH_PATH`, `AUTH_ARGS`, `AUTH_TIMEOUT_MS`, `AUTH_REFRESH_INTERVAL_MS` 설정을 추가했다.
- MCP 인증 에러 발생 시 `refresh_auth`를 먼저 시도한다.
- `refresh_auth` 실패 시 MCP 프로세스를 재시작하고 다시 갱신을 시도한다.
- 그래도 실패하면 `notebooklm-mcp-auth` CLI를 브리지 서버가 직접 실행한다.
- CLI 인증 후 MCP 프로세스를 재시작해 새 토큰을 읽게 만든다.
- 장시간 실행 중에는 15분 간격으로 요청이 없는 시점에 인증 상태를 사전 갱신한다.
- UI 안내 문구를 수동 재인증 중심에서 자동 복구 중심으로 수정했다.
## Runtime Behavior
새 인증 복구 순서:
1. NotebookLM MCP 요청 실패
2. 에러 메시지가 인증 관련인지 판단
3. `refresh_auth` 호출
4. MCP 프로세스 재시작 후 `refresh_auth` 재시도
5. `notebooklm-mcp-auth` CLI 자동 실행
6. MCP 프로세스 재시작
7. 원래 실패했던 NotebookLM 요청 재시도
주기적 갱신:
- 기본 간격: 15분
- 설정값: `AUTH_REFRESH_INTERVAL_MS=900000`
- 진행 중인 MCP 요청이 있을 때는 건드리지 않고 건너뛴다.
## Verification
실행한 검증:
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
npm run bridge
curl -s http://127.0.0.1:3002/api/health
```
검증 결과:
- `node --check` 통과
- TypeScript 타입체크 통과
- 브리지 서버 시작 성공
- MCP 서버 초기화 성공
- `/api/health`에서 `connected: true`, `version: 3.3.0`, `authPath` 확인
## Notes
완전히 백그라운드 인증이 가능한지는 Google/Chrome 세션 상태에 의존한다.
브라우저 로그인이 만료되어 실제 사용자 로그인이 필요한 상태라면 자동 CLI 실행도 브라우저 로그인을 요구할 수 있다.
다만 기존처럼 매번 사용자가 batch 파일을 직접 실행하는 흐름보다, 일반적인 토큰 만료와 MCP refresh 실패 상황은 브리지 서버가 먼저 복구하도록 개선되었다.
@@ -0,0 +1,60 @@
# Datacollector - NotebookLM 자동 재인증 검증 강화 및 동시 복구 잠금
- 작성 시각: 2026-04-25 22:17:33 KST
- 프로젝트: `/Volumes/Data/project/Antigravity/Datacollector`
- 관련 파일: `scripts/mcp_bridge.mjs`
## 상황
인증 브라우저 유지와 오래된 `.env` 쿠키 우선순위 문제를 해결한 뒤에도, 실제 작업 중 인증이 풀렸을 때 완전히 자동으로 재인증되지 않는 문제가 남아 있었다.
화면에서는 작업은 진행되지만 사용자가 기대한 "인증 만료 감지 -> 자동 재인증 -> 원래 작업 재시도" 흐름이 안정적으로 보장되지 않았다.
## 원인
브리지에는 자동 복구 로직이 있었지만 두 가지 빈틈이 있었다.
- `refresh_auth` 호출이 성공해도 실제 NotebookLM API 호출이 가능한지 검증하지 않았다.
- `/api/re-auth``/api/check-connection` 같은 요청이 동시에 들어오면 각각 MCP 재시작과 인증 복구를 시도해서 프로세스 재시작 경합이 생길 수 있었다.
추가로 인증 오류 판별 문자열에 `expired`, `RPC Error 16`, `csrf`, `만료` 같은 케이스가 충분히 포함되지 않아 일부 인증 만료 메시지가 일반 오류로 처리될 가능성이 있었다.
## 조치
`scripts/mcp_bridge.mjs`에서 다음을 수정했다.
- 재인증 성공 기준을 `refresh_auth` 성공이 아니라 실제 `notebook_list` 호출 성공으로 강화했다.
- 인증 만료 감지 시 `refreshAuth({ allowExternalAuth: true })`를 통해 자동 CLI 인증 복구까지 이어지도록 정리했다.
- 주기적 인증 점검도 필요 시 외부 인증 CLI 복구를 허용하도록 변경했다.
- `_refreshAuthPromise` 잠금을 추가해 동시 재인증/재시작 요청이 서로 충돌하지 않게 했다.
- 인증 오류 감지 키워드에 `expired`, `rpc error 16`, `csrf`, `unauthorized`, `forbidden`, `인증`, `만료`를 추가했다.
## 검증
다음 검증을 완료했다.
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
curl -sS -X POST http://127.0.0.1:3002/api/re-auth
curl -sS -X POST http://127.0.0.1:3002/api/check-connection
```
결과:
- `/api/re-auth`: `success: true`
- `/api/check-connection`: `success: true`
또한 `/api/re-auth``/api/check-connection`을 동시에 호출해도 둘 다 성공하는 것을 확인했다.
## 운영 메모
이제 인증이 풀린 상태에서 NotebookLM MCP 호출이 인증 오류를 반환하면 브리지가 다음 순서로 자동 복구한다.
1. MCP의 `refresh_auth` 실행
2. 실제 `notebook_list` 호출로 인증 유효성 검증
3. 실패 시 MCP 프로세스 재시작 후 재검증
4. 그래도 실패하면 `notebooklm-mcp-auth` CLI 실행
5. 인증 캐시 정리 후 MCP 재시작 및 실제 호출 검증
NotebookLM 브라우저 세션이 완전히 로그아웃된 상태라면 자동 CLI도 브라우저 로그인을 요구할 수 있다. 이 경우 사용자가 열린 NotebookLM Chrome 창에서 로그인만 해두면 이후 자동 복구가 다시 이어질 수 있다.
@@ -0,0 +1,84 @@
# Datacollector NotebookLM Connection Guard and MCP Restart Fix
Date: 2026-04-25 21:02:35 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
실행 중 NotebookLM 연결 체크가 500 에러를 반환한 뒤에도 미션이 계속 시작되어 Local LM fallback으로 넘어가고, 결국 `Local LM returned an empty or invalid response` 에러가 발생했다.
또한 브리지의 MCP 재시작 로직에서 자동 재시작과 수동 재시작이 겹쳐 여러 `notebooklm-mcp` 프로세스가 남는 문제가 확인되었다.
## Observed Errors
브라우저 콘솔:
```text
:3000/favicon.ico 404 (Not Found)
127.0.0.1:3002/api/check-connection 500 (Internal Server Error)
```
앱 로그:
```text
NotebookLM 연결 실패: 인증 자동 복구 실패...
GENERAL MODE
ENGINE ERROR Local LM returned an empty or invalid response.
```
## Root Causes
1. `testNotebookLmConnection()`이 성공 여부를 반환하지 않았다.
2. `handleStart`, `handleResume`, `handleGlobalResume`이 연결 실패 후에도 그대로 `running` 상태로 넘어갔다.
3. `restart()`가 MCP 프로세스 종료 이벤트를 기다리지 않고 바로 새 프로세스를 띄울 수 있었다.
4. `close` 이벤트의 자동 재시작이 수동 재시작과 겹쳐 MCP 하위 프로세스가 누적될 수 있었다.
5. favicon 파일이 없어서 브라우저가 `/favicon.ico` 기본 요청을 404로 표시했다.
## Changes Made
수정 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
- `/Volumes/Data/project/Antigravity/Datacollector/index.html`
추가 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/public/favicon.svg`
핵심 변경:
- `testNotebookLmConnection()``Promise<boolean>`을 반환하도록 변경
- NotebookLM 연결 실패 시 신규 미션 시작, 개별 재개, 전체 재개를 보류
- 연결 실패 후 Local LM fallback으로 자동 진행되는 흐름 차단
- MCP 프로세스를 종료할 때 `close` 이벤트를 기다리는 `_stopCurrentProcess()` 추가
- 재시작 중 자동 재시작이 중복 실행되지 않도록 제어
- 재시작 테스트 후 MCP 하위 프로세스가 하나만 남는지 확인
- SVG favicon 추가 및 `index.html`에 명시
## Verification
실행한 검증:
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
npm run build
npm run bridge
curl -s http://127.0.0.1:3002/api/health
curl -s -X POST http://127.0.0.1:3002/api/restart
```
검증 결과:
- 브리지 문법 체크 통과
- TypeScript 타입체크 통과
- Vite 빌드 통과
- 브리지 시작 성공
- `/api/health` 응답 정상
- `/api/restart``notebooklm-mcp` 프로세스가 하나만 남는 것 확인
## Operational Note
현재 실행 중이던 오래된 브리지와 누적된 MCP 하위 프로세스는 종료했다.
앱은 다시 실행해야 새 브리지 로직이 적용된다.
@@ -0,0 +1,70 @@
# Datacollector NotebookLM Progress Visibility and Auth Diagnosis
Date: 2026-04-25 21:17:24 KST
Project: Datacollector
Repository: `/Volumes/Data/project/Antigravity/Datacollector`
## Summary
사용자가 UI에서 `NotebookLM 연결 상태 점검 중...` 로그만 반복되고 실제 진행 상황을 알 수 없다고 보고했다.
확인 결과 앱이 프로젝트 생성 단계까지 가지 못하고 있었으며, 원인은 NotebookLM 연결 확인 단계에서 MCP 인증이 만료 상태로 판단되기 때문이었다.
## Observed State
확인한 상태:
- Vite 서버 `3000` 실행 중
- MCP Bridge 서버 `3002` 실행 중
- `notebooklm-mcp` 프로세스 실행 중
- `/api/health` 응답 가능
- `/api/check-connection`은 NotebookLM 인증 만료 오류 반환
브리지 로그상 자동 인증 CLI는 Chrome을 열고 로그인 및 토큰 추출까지 수행했다.
그러나 MCP 서버는 이후에도 `Authentication expired`로 판단하여 NotebookLM notebook list 호출에 실패했다.
## Changes Made
수정 파일:
- `/Volumes/Data/project/Antigravity/Datacollector/scripts/mcp_bridge.mjs`
- `/Volumes/Data/project/Antigravity/Datacollector/src/components/AgentDashboard.tsx`
핵심 변경:
- MCP 초기화 타임아웃 추가: `MCP_INIT_TIMEOUT_MS`
- NotebookLM 연결 확인 타임아웃 추가: `MCP_HEALTH_TIMEOUT_MS`
- `/api/health`에 상세 상태 추가
- `initialized`, `processRunning`, `processPid`, `pendingRequests`, `authStatus` 노출
- 인증 CLI 진행 단계(`starting`, `running`, `restarting`, `success`, `failed`) 추적
- UI 연결 점검 중 5초마다 Bridge/MCP/auth 진행 상태 로그 출력
- 중복 연결 점검 요청은 기존 Promise를 재사용하도록 변경
## Verification
실행한 검증:
```bash
node --check scripts/mcp_bridge.mjs
npm run lint
npm run build
curl -sS --max-time 5 http://127.0.0.1:3002/api/health
curl -sS --max-time 25 -X POST -H 'Content-Type: application/json' -d '{}' http://127.0.0.1:3002/api/check-connection
```
검증 결과:
- 브리지 문법 체크 통과
- TypeScript 타입체크 통과
- Vite 빌드 통과
- Bridge/MCP 프로세스는 실행됨
- NotebookLM 연결 확인은 인증 만료 오류로 실패
## Current Diagnosis
현재 문제는 앱 실행이나 Bridge 연결 문제가 아니라 NotebookLM MCP 인증 상태 문제다.
자동 인증 CLI가 토큰을 저장해도 MCP 서버가 계속 만료로 판단하므로, 다음 단계에서는 NotebookLM MCP 패키지의 인증 저장 형식 또는 권장 인증 방식(`--file` 모드 등)을 확인해야 한다.
## Operational Note
확인용으로 실행했던 Bridge/Vite/MCP 프로세스는 종료했다.
새 진행 상태 로그를 보려면 앱을 `run_mac.command`로 다시 실행해야 한다.
@@ -0,0 +1,173 @@
# Skybound Core Gameplay Rebalance and Purpose Reset
**Date**: 2026-04-25
**Project**: Skybound Protocol
**Author**: Codex
**Status**: Raw corrective gameplay pass after balance regression
## 1. User Playtest Feedback
The previous balance pass made the game worse.
Observed issues:
- TAC Level Up triggered repeatedly and too quickly.
- Campaign and Blitz did not communicate a clear purpose.
- It was unclear whether the player should dodge bullets, collect upgrades, survive waves, or simply idle.
- Standing near the center could clear the stage with little interaction.
- Skill choice did not feel strategic because almost any pickup worked.
- The foundation felt like it had grown without a clear gameplay plan.
## 2. Diagnosis
The previous pass overcorrected toward reward frequency and enemy density.
Main problems:
- initial EXP requirement was too low
- EXP gem values were too high
- level-up carryover allowed too much momentum
- no cooldown existed between TAC Level Up events
- base magnet radius was too generous
- base damage multiplier was too high
- weapon cooldowns became too generous
- enemy caps became too high for the current combat model
- enemies were too weak for the amount of automatic player damage
The result was a reward flood without enough danger, movement, or tactical pressure.
## 3. New Gameplay Purpose
Skybound should not be a pure bullet hell and should not be an idle auto-clear game.
The intended player loop should be:
1. Survive incoming enemy formations and hazard pressure.
2. Move deliberately to collect EXP gems and supply rewards.
3. Choose upgrades that solve the current pressure pattern.
4. Build toward synergies and evolutions.
5. Enter boss or spike phases with a build that feels earned.
The main fun should come from:
- movement under pressure
- risk-reward EXP collection
- tactical skill choices
- visible power growth
- stage pressure that asks for different answers
The player should not be able to win reliably by standing still.
## 4. Corrective Fixes Applied
### TAC Level Up Flood Control
Applied:
- initial required EXP increased from `45` to `90`
- normal enemy EXP reduced from `7` to `4`
- elite EXP reduced from `32` to `20`
- level-up multiplier increased to `1.42 / 1.48 / 1.55 / 1.62`
- added a `360 frame` TAC Level Up lockout after each level-up
- EXP carryover is capped to `35%` of the next requirement
Expected result:
- level-up moments become meaningful beats
- no rapid-fire modal spam
- players must keep playing between upgrades
### Movement Incentive
Applied:
- base magnet radius reduced from `180` to `90`
- magnet passive now adds `35` per level instead of `60`
Expected result:
- EXP collection requires movement
- standing still misses more progression
- magnet becomes a strategic comfort/passive choice rather than free global collection
### Idle-Clear Reduction
Applied:
- base effective damage reduced from `1.5` to `1.0`
- damage passive now provides growth from deliberate investment
- several weapon cooldowns were pulled back from the previous overly generous pass
- Nova Burst was returned closer to a periodic tactical tool rather than constant auto-clear
Expected result:
- early weapons no longer erase all pressure automatically
- skill investment matters more
- AoE tools help but do not replace positioning
### Enemy Pressure Recentered
Applied:
- hard enemy cap reduced from `90` to `56`
- phase caps reduced from the previous overcorrection
- enemy HP increased from the previous too-low values
- enemies enter deeper into the playfield
- enemy speed and bullet pressure were slightly restored
- procedural spawn cadence reduced from the flood state
Expected result:
- fewer meaningless bodies
- enemies apply actual positional pressure
- player must dodge, reposition, and collect intentionally
## 5. Design Rule Going Forward
Future balance changes should follow this rule:
Do not increase rewards unless a matching risk or movement requirement exists.
Examples:
- faster level-up needs harder collection or less carryover
- more enemies need weaker auto-clear or stronger enemy pathing
- stronger skills need clearer spike counters or enemy behaviors
- more pickups need better pickup affordance and danger around pickup zones
## 6. Changed Runtime Paths
Important changed paths:
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/store/useGameStore.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/types.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ProgressionSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/CombatSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/SpawnerSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/CombatTimeline.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/balance.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/weaponBehaviors.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ModularWeaponSystem.ts`
## 7. Verification
Production build completed successfully with:
```bash
npm run build
```
The existing `/sprites/player.png` static asset warning remains non-blocking.
## 8. Next Necessary Design Work
This corrective patch stabilizes the worst problems, but the project still needs a stronger core design pass.
Recommended next work:
- define Campaign as objective-based stages with unique pressure patterns
- define Blitz as score/survival mode with explicit risk-reward scoring
- add clear stage objectives to HUD
- add enemy archetypes that force movement differently
- add pickup-risk zones so rewards are not free
- review every skill for role identity: damage, crowd control, defense, mobility, economy
@@ -0,0 +1,103 @@
# Skybound Player Airframe and 8 Stage Boss Continuity Rework
작성일: 2026-04-25 09:51 KST
## 요청 요약
- 사용자 기체가 엔진에서 그린 도형 조립처럼 보여 시각적 완성도가 낮아 보이는 문제를 개선한다.
- Stage 1 클리어 후 Stage 2로 넘어가는 흐름이 결과 화면으로 끊겨 게임이 단절되는 문제를 개선한다.
- Aero Fighters처럼 보스를 처치하고 같은 런 안에서 다음 스테이지로 자연스럽게 이어지는 구조를 만든다.
- 총 8개 스테이지를 유지하고, 스테이지가 올라갈수록 난이도가 올라가도록 보스 HP, 파츠, 패턴을 재조정한다.
- 각 스테이지 보스가 서로 다른 공격 패턴을 체감할 수 있도록 실행부를 보강한다.
## 확인한 문제
### 플레이어 기체 렌더링
- `GameRenderer.renderPlayer()`에서 플레이어 스프라이트 위에 랜덤 원형 엔진 글로우를 직접 그려서, 기체 뒤쪽이 매 프레임 흔들리는 임시 도형처럼 보였다.
- `renderWeaponAttachments()`에서 일부 장착 무기를 `fillRect`, `strokeRect`, 랜덤 원형 플래시로 그려서 톤앤매너에 맞는 완성형 파츠가 아니라 디버그 박스처럼 보일 수 있었다.
- 특히 Hyper Sonic Vulcan, Gatling fallback, Missile Pod fallback이 사용자 기체 실루엣과 잘 섞이지 않았다.
### 스테이지 전환
- 보스 처치 후 `STAGE_CLEAR`가 되고, 300프레임 뒤 `BOSS_ACTION NEXT_STAGE` 이벤트가 발생한다.
- 기존 `useGameEngine`은 이 이벤트를 곧바로 `finishMission('CLEAR')`로 연결했다.
- 그 결과 Standard 캠페인에서도 Stage 1 보스 처치 후 결과 화면으로 끊기고, 다음 스테이지는 별도 런처럼 느껴졌다.
### 보스 패턴
- `bossActions.ts`에는 Stage 1부터 Stage 8까지 액션 테이블이 있다.
- 하지만 `BossSystem.executePattern()`은 일부 액션만 처리하고 있었기 때문에, 실제 전투에서는 많은 액션이 기본 단발 탄으로 떨어질 수 있었다.
- `StageDirectorSystem.instantiateBoss()`의 보스 파츠 turretId가 `T-CORE`, `T-WING`, `T-HEAVY`처럼 실제 `TURRET_CATALOG`에 없는 값이라 파츠 포탑이 의도대로 발사되지 않을 수 있었다.
- 기존 보스 HP는 Stage 2부터 `5000 * currentStage`로 급격히 올라가 캠페인 커브가 자연스럽지 않았다.
## 적용한 변경
### 플레이어 기체 완성도 개선
- 플레이어 엔진 글로우를 랜덤 원형에서 고정된 마기테크 추진 플룸으로 변경했다.
- 스프라이트 크기를 72px에서 78px로 약간 키워 중심 기체의 존재감을 높였다.
- `drawMagitechPod()` 헬퍼를 추가해 장착 무기를 작은 마기테크 포드 형태로 통일했다.
- Vulcan, Gatling fallback, Missile Pod fallback을 박스 도형 대신 다크 블루 메탈 바디, 시안/옐로/핑크 액센트, 라운드 포드 실루엣으로 렌더링한다.
- 장착 파츠의 랜덤 플래시를 줄이고 프레임 기반 pulse로 바꿔 덜 튀고 더 의도적으로 보이게 했다.
### 연속 캠페인 전환
- Standard 캠페인에서 Stage 1-7 보스 처치 후 `finishMission`을 호출하지 않고, 같은 엔진 런 안에서 다음 스테이지로 전환하도록 변경했다.
- 전환 시 다음 작업을 수행한다.
- `currentStage` 증가
- `campaignStageIndex` 저장
- `StageDirectorSystem.advanceToStage()`로 새 타임라인 로드
- 활성 총알, 적, 파티클 풀 정리
- 스포너 큐 초기화
- 보스, 탄막, hazard, airdrop, exp gem, vortex 정리
- `INTRO` 페이즈로 재시작
- 체력 25% 회복과 120프레임 무적 부여
- Stage 안내 텍스트와 HQ comms 출력
- Stage 8 보스 처치 시에는 `GAME_COMPLETE`로 결과 화면에 진입한다.
- Blitz 모드는 기존처럼 단일 전투 클리어로 유지한다.
### 8스테이지 보스 커브
- 보스 HP를 선형 폭증에서 완만한 곡선형 성장으로 변경했다.
- Stage 1은 낮게 시작하고, Stage 8은 누적 성장과 보스 패턴 난이도를 고려해 높은 난이도를 갖도록 설계했다.
- 보스 파츠 HP도 같은 stage curve를 사용해 코어, 날개, 포탑이 함께 성장한다.
- 각 스테이지에 실제 `TURRET_CATALOG`에 존재하는 turretId loadout을 지정했다.
### 보스 패턴 실행 보강
- 다음 액션들이 실제 탄막/기믹으로 실행되도록 매핑했다.
- `FAN_PART`, `DASH_PART`: 부채꼴 조준 사격
- `SIDE_WAVE`: 좌우 측면 웨이브
- `ZONE_BOMB`: 안전 구역 압박과 링 탄막
- `WALL_WAVE`: 틈이 있는 벽 형태 탄막
- `MISSILE_BARRAGE`, `HOMING_CHASE`: 유도성 탄막
- `CROSS_CHASE`: 네 방향 교차 추격 탄
- `SPIRAL_WEB`, `REVOLVING_FLAME`: 나선 탄막
- `BURST_SPLITTER`: 분열형 부채 탄
- `GEAR_STORM`: 고밀도 나선과 링 조합
- `PRECISION_LOCK`, `SNIPE_GRID`, `LASER_AIM`, `LASER_SWEEP`: 크로스헤어 기반 고속 압박
- `TELEPORT_STRIKE`: 보스 위치 변경 후 기습 사격
- `GIMMICK_PULSE`, `CC_REVERSE`, `ZONE_COLLAPSE`: 중력장/페이즈존 기믹과 링 탄막
- `ULTIMATE_SYMPHONY`: 기존 고난도 복합 패턴 유지
## 수정 파일
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/GameRenderer.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameEngine.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/StageDirectorSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/BossSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/EntityManager.ts`
## 검증
- `npm run build` 성공
- Vite 경고: `/sprites/player.png referenced in /sprites/player.png didn't resolve at build time`
- 위 경고는 기존 런타임 경로 관련 경고이며 이번 변경으로 인한 빌드 실패는 아니다.
## 후속 플레이테스트 포인트
- Stage 1 보스 처치 후 결과 화면 없이 Stage 2 INTRO로 자연스럽게 이어지는지 확인한다.
- Stage 8 보스 처치 후 `GAME_COMPLETE` 결과로 진입하는지 확인한다.
- 장착 무기 파츠가 기체와 과하게 분리되어 보이지 않는지 확인한다.
- Stage 3 이후 `ZONE_BOMB`, `WALL_WAVE`, `HOMING_CHASE`, `PRECISION_LOCK` 계열이 회피 목적을 명확히 만드는지 확인한다.
@@ -0,0 +1,75 @@
# Skybound Skill Concept and Hangar Layout Overlap Fix
작성일: 2026-04-25 10:09 KST
## 요청 요약
- 스킬 업그레이드 후 화면에 긴 라이트 기둥만 보이는 문제가 있어 스킬 개념과 연출을 수정한다.
- HUD/UI 관점에서 왼쪽에 여러 UI가 겹쳐 나오는 문제가 있어 필요하면 전체적으로 재설계한다.
## 확인한 문제
### Hyper-Sonic Vulcan 컨셉 불일치
- `Hyper-Sonic Vulcan`은 이름상 고속 벌컨/캐논 계열인데 실제 구현은 영구 지속되는 긴 레이저 빔이었다.
- `GameRenderer`가 플레이어 기준으로 화면 끝까지 이어지는 두꺼운 시안 빔을 그려서, 스킬이 무기라기보다 긴 조명처럼 보였다.
- `ModularWeaponSystem.updateHyperLaser()`도 라인 판정으로 지속 데미지를 넣고 있어 플레이어가 발사/탄막을 체감하기 어려웠다.
### Hangar UI 겹침
- `HangarOverlay.tsx`에서 `UPGRADE``PASS` 탭 콘텐츠가 오른쪽 `craft-area` 패널 밖에 렌더링되고 있었다.
- 그 결과 CSS Grid의 세 번째 아이템처럼 배치되어 왼쪽 패널/재료 영역과 겹쳐 보였다.
- 특히 `UPGRADE` 탭 선택 시 `PERMANENT UPGRADES` 콘텐츠가 왼쪽 재료 패널 위로 올라오는 문제가 발생했다.
### 전투 보상 텍스트 겹침
- 적 처치 보상 텍스트가 화면 가장자리에서 생성될 경우 `TechMats`, `+TAC` 같은 텍스트가 잘리거나 서로 겹쳐 보일 수 있었다.
## 적용한 변경
### Twin Arc Vulcan으로 스킬 컨셉 변경
- `HYPER_SONIC_VULCAN` 메타데이터 이름을 `Twin Arc Vulcan`으로 변경했다.
- 설명도 `Twin magitech cannons fire rapid piercing arc rounds.`로 바꿔 실제 플레이 감각과 맞췄다.
- 기존의 영구 레이저 빔 컨셉을 제거하고, 전방 관통 아크 탄환을 빠르게 발사하는 무기로 재설계했다.
- 플레이어 좌우 포드에서 3갈래 관통탄을 빠르게 발사해 “벌컨 업그레이드” 느낌을 강화했다.
- 스킬이 화면을 덮는 긴 빛이 아니라, 방향성과 탄막 밀도가 있는 공격으로 보이게 했다.
### 긴 라이트 렌더링 제거
- `GameRenderer`의 full-screen beam `fillRect()` 렌더링을 제거했다.
- 대신 기체 앞쪽 포드에 짧은 muzzle bloom과 짧은 시안 streak만 표시하도록 변경했다.
- 화면 전체를 가리는 시각 노이즈를 줄이고, 실제 공격은 projectile 렌더링이 담당하게 했다.
### Hangar 탭 레이아웃 수정
- `UPGRADE``PASS` 탭 콘텐츠를 오른쪽 `craft-area` 내부로 이동했다.
- 이제 탭 콘텐츠가 왼쪽 `Airframe Telemetry`/`Materials` 패널과 겹치지 않는다.
- 기존 스타일을 유지하면서 구조적 렌더링 오류를 먼저 제거했다.
### Floating Text 안전 영역 처리
- `ctx.spawnText()`에서 텍스트 생성 위치를 화면 안전 영역 안으로 clamp한다.
- 왼쪽 끝/오른쪽 끝에서 적이 죽어도 보상 텍스트가 화면 밖으로 잘리거나 HUD 영역에 과하게 겹치는 현상을 줄였다.
## 수정 파일
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ModularWeaponSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/GameRenderer.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/evolutions.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/config/weaponBehaviors.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HangarOverlay.tsx`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameEngine.ts`
## 검증
- `npm run build` 성공
- Vite 경고: `/sprites/player.png referenced in /sprites/player.png didn't resolve at build time`
- 위 경고는 기존 런타임 경로 경고이며 이번 변경으로 인한 빌드 실패는 아니다.
## 후속 플레이테스트 포인트
- Gatling 진화 후 더 이상 긴 레이저 기둥이 보이지 않는지 확인한다.
- `Twin Arc Vulcan`이 빠른 관통 탄막 무기로 체감되는지 확인한다.
- Hangar에서 `UPGRADES`, `EVENT PASS` 탭 선택 시 왼쪽 패널과 콘텐츠가 겹치지 않는지 확인한다.
- 전투 보상 텍스트가 화면 가장자리에서 잘리지 않는지 확인한다.
@@ -0,0 +1,105 @@
# Skybound Tac EXP Direct Kill and UI Productization Pass
작성일: 2026-04-25 10:01 KST
## 요청 요약
- Tac Level 경험치는 적기를 처치했을 때 바로 획득하게 한다.
- 바닥에 경험치 파티클/젬이 떨어져 화면을 어지럽히지 않게 한다.
- 너무 빠른 레벨업으로 난이도 밸런스가 무너지는 문제를 완화한다.
- Hangar, HUD, Tac Level Up 등 아직 남아 있는 예전 UI 톤을 Stylized Casual Magitech 톤앤매너에 맞게 통일한다.
- `THRUST_OUTPUT`처럼 작동하지 않거나 내부 시스템 문자열처럼 보이는 UI 문구를 상품성 있게 정리한다.
## 확인한 문제
### Tac EXP
- `CombatSystem`이 적 사망 시 `spawnExpGem()`을 호출해 바닥에 경험치 젬을 생성하고 있었다.
- `ProgressionSystem`은 바닥 젬의 이동, 자석 흡수, 수집을 통해 경험치를 지급했다.
- 적 밀도가 올라갈수록 젬이 많이 쌓이고, 화면 가독성과 레벨업 속도 모두 불안정해질 수 있었다.
- 기존 젬 값은 일반몹/엘리트몹 기준으로 레벨업을 빠르게 밀어 올리는 구조였다.
### HUD 문구
- `SYSTEM_ACTIVE`, `TAC_LEVEL`, `HIGH_SCORE_SYNC`, `COMBO_LINK`, `ENERGY_CELL`, `LOCK_ON`, `HEAT_SIG`, `SHIELD_OS`, `THRUST_OUTPUT` 같은 내부 변수명 스타일 문구가 사용자에게 그대로 노출되고 있었다.
- `THRUST_OUTPUT``dodgeCooldownPct`를 읽지만 엔진에서 값을 갱신하지 않아 실질적으로 반응하지 않는 상태였다.
### Hangar UI
- 장비 카드가 빈 박스처럼 보이며 아이템명/레벨/스탯 정보가 충분히 드러나지 않았다.
- 탭 이름과 슬롯 이름이 기능적이지만 상품 화면처럼 자연스럽지는 않았다.
- 전체 스타일이 이전의 얇은 선, 어두운 반투명 박스 중심이라 현재 게임의 굵은 외곽선/밝은 마법 액센트 톤과 어긋났다.
## 적용한 변경
### Tac EXP 직접 지급
- `CombatSystem`에서 적 사망 시 더 이상 `spawnExpGem()`을 호출하지 않는다.
- 대신 `ctx.grantTacExp()`를 통해 처치 즉시 경험치를 지급한다.
- 일반 적: `+1 TAC`
- 엘리트 적: `+5 TAC`
- 미드 보스: `+16 TAC`
- 엘리트 이상만 짧은 `+TAC` 텍스트 피드백을 표시해 화면 노이즈를 줄였다.
- 바닥 경험치 젬은 신규 생성되지 않으므로, 플레이 중 먹을 수 없는 파란 점/구슬이 쌓이는 문제가 사라진다.
### 레벨업 속도 완화
- `ProgressionSystem.grantExp()`를 추가해 직접 경험치 지급과 기존 젬 수집 지급을 한 곳에서 처리한다.
- Spike 전 EXP 부스트는 최대 `x1.25`로 제한했다.
- 기존 레벨업 lockout과 carryover cap은 유지해 연속 레벨업 폭주를 방지한다.
### HUD 상품성 개선
- `HIGH_SCORE_SYNC``Best Run`
- `SYSTEM_ACTIVE``Falcon Online`
- `TAC_LEVEL``Tactical Level`
- `THRUST_OUTPUT``Afterburner`
- `ENERGY_CELL``Hull Core`
- `COMBO_LINK``Chain Bonus`
- `LOCK_ON``Lock-On`
- `HEAT_SIG``Heat Trace`
- `SHIELD_OS``Guard Field`
- 페이즈 표시도 `BOSS_WARNING` 같은 내부 enum 대신 `Boss Incoming`, `Horde Surge`, `Route Secured` 같은 플레이어용 문구로 매핑했다.
- 엔진에서 `setDodgeCooldownPct()`를 실제 dodge 상태에 맞게 갱신해 Afterburner 게이지가 부스트 중 반응하도록 연결했다.
### Hangar UI 톤 통일
- Hangar 배경과 패널을 Stylized Casual Magitech 톤으로 보강했다.
- 굵은 네이비 외곽선, 청록/민트/골드 마법 액센트, 둥근 카드, 명확한 hover 피드백을 적용했다.
- 장비 카드에 아이템 타입, 이름, 레벨, ATK, HP가 보이도록 개선했다.
- 탭 이름을 `LOADOUT`, `SYNTHESIS`, `SALVAGE`, `ASTRAL FORGE`, `UPGRADES` 등 더 자연스러운 메뉴명으로 바꿨다.
- 빈 슬롯 문구를 `NO MODULE`에서 `Available mount`로 바꿨다.
- `SYSTEM MOUNTS`, `MODULE STORAGE`를 각각 `Mount Bays`, `Module Storage`로 정리했다.
### Level Up 모달 문구 개선
- `TAC LV`, `TAC LEVEL UP!`, `SELECT TACTICAL ENHANCEMENT` 중심의 시스템 문자열 느낌을 줄였다.
- 일반 레벨업: `Tactical Upgrade`
- 시작 선택: `Choose First Weapon`
- 보급 선택: `Emergency Supply`
- 카드 문구도 `NEW ACQUISITION`에서 `New module`로 완화했다.
## 수정 파일
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/CombatSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/ProgressionSystem.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/systems/types.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameEngine.ts`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HUDOverlay.tsx`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HangarOverlay.tsx`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HangarOverlay.css`
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/LevelUpModal.tsx`
## 검증
- `npm run build` 성공
- Vite 경고: `/sprites/player.png referenced in /sprites/player.png didn't resolve at build time`
- 위 경고는 기존 런타임 경로 경고이며 이번 변경으로 인한 빌드 실패는 아니다.
- 주요 내부 문자열 검색 결과, 요청에서 지적된 `SYSTEM_ACTIVE`, `THRUST_OUTPUT`, `TAC_LEVEL`, `HIGH_SCORE_SYNC`, `COMBO_LINK`, `ENERGY_CELL`, `LOCK_ON`, `HEAT_SIG`, `SHIELD_OS`는 현재 게임 UI 코드에서 제거되었다.
## 후속 플레이테스트 포인트
- 적 처치 후 바닥에 경험치 젬이 신규로 생성되지 않는지 확인한다.
- 일반몹을 많이 잡아도 Tac Level이 연속 폭주하지 않는지 확인한다.
- Afterburner 게이지가 회피/부스트 중 시각적으로 반응하는지 확인한다.
- Hangar 장비 카드가 더 이상 빈 회색 박스처럼 보이지 않고 아이템 정보를 명확히 보여주는지 확인한다.
@@ -0,0 +1,25 @@
# [[Automatic Batching]]
## 📌 Brief 시 Summary
Automatic Batching(자동 배칭)은 React 18에 도입된 기능으로, 여러 상태(State) 업데이트를 하나의 리렌더링으로 그룹화하여 처리하는 성능 최적화 기법입니다 [1-3]. 이전 버전에서는 React의 네이티브 이벤트 핸들러 내의 업데이트만 배칭되었으나, React 18부터는 프로미스(Promise), setTimeout, 비동기 작업 등 출처와 무관하게 모든 상태 업데이트를 자동으로 배칭합니다 [2, 4-6]. 이를 통해 불필요한 리렌더링과 Virtual DOM의 비교 연산(diffing)을 최소화하여 애플리케이션의 성능과 UI 응답성을 크게 향상시킵니다 [4, 7].
## 📖 Core Content
* **작동 원리 및 도입 배경:**
React 18 이전에는 `onClick`과 같은 React 내부 이벤트 핸들러에서 발생하는 상태 업데이트만 배칭 처리가 되었습니다 [2, 6]. 따라서 `setTimeout`이나 비동기 API 호출 내에서 상태를 여러 번 업데이트할 경우, 각 업데이트마다 개별적인 리렌더링이 발생하여 성능 저하의 원인이 되었습니다 [2, 8]. React 18의 자동 배칭 기능은 이벤트 출처와 상관없이 모든 상태 업데이트를 하나로 묶어(Batch) 단 한 번의 렌더링과 DOM 업데이트만 트리거합니다 [3, 7, 9, 10].
* **렌더링 성능 최적화 효과 ("React가 빠른 이유"):**
자동 배칭은 여러 상태 변경이 짧은 시간 안에 연속적으로 발생할 때 불필요한 리렌더링의 수를 줄여줍니다 [10, 11]. 리렌더링 횟수가 감소하면 Virtual DOM의 비교 연산(Diffing)과 CPU 작업량이 최소화됩니다 [1, 4]. 실제로 데이터 집약적인 대시보드 환경에서 자동 배칭을 적용한 결과, 전체 렌더링 횟수가 약 40% 감소하고 피크 로드 시 프레임 속도가 25% 향상되는 등 눈에 띄는 성능 개선을 보여주었습니다 [1, 12]. 이는 "Reflow"와 "Repaint"를 유발하는 브라우저의 DOM 조작 빈도를 줄이는 핵심적인 최적화 원리 중 하나입니다 [7].
* **자동 배칭 제어 및 예외 처리 (Opt-Out):**
개발자가 의도적으로 자동 배칭을 우회하고 상태 업데이트 즉시 DOM에 반영해야 하는 상황이 존재할 수 있습니다. 예를 들어, 사용자의 폼 입력에 즉각적인 피드백을 주거나 렌더링 직후 DOM 요소의 크기를 측정해야 하는 경우입니다 [13]. 이때는 React DOM에서 제공하는 `flushSync` API를 사용하여 강제로 즉각적인 동기적 리렌더링을 발생시킬 수 있습니다 [12-15]. 반대로, 긴급하지 않은 대규모 업데이트(예: 리스트 필터링)의 경우 `startTransition`을 사용하여 우선순위를 낮추고 UI 차단을 방지할 수 있습니다 [12, 13].
* **주의사항 및 디버깅:**
자동 배칭은 기본적으로 제공되는 최적화지만, 일부 서드파티 상태 관리 도구나 UI 라이브러리가 React의 이벤트 시스템을 우회하는 방식으로 동작할 경우 배칭이 제대로 적용되지 않을 수 있습니다 [16, 17]. 이러한 예외 상황을 식별하기 위해서는 React DevTools Profiler를 사용하여 컴포넌트의 렌더링 횟수와 업데이트 트리거를 모니터링하는 것이 권장됩니다 [16].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[React가 빠른 이유]], [[Reflow / Repaint 최소화 방법]]
- **Projects/Contexts:** [[React 18]], [[Performance Optimization]]
- **Contradictions/Notes:** 자동 배칭은 성능을 크게 향상시키지만 무조건적으로 유용한 것은 아닙니다. 폼의 입력 값 업데이트나 요소 포커싱처럼 사용자에게 지연 없는 즉각적 피드백을 제공해야 하는 필수적인 상황에서는 `flushSync`를 사용해 배칭을 해제해야 하며, 이를 남용할 경우 배칭으로 얻는 성능 이점을 상쇄할 수 있으므로 주의해야 합니다 [13, 18]. 또한 서드파티 라이브러리 통합 시 React 이벤트 시스템을 우회하면 자동 배칭이 무력화될 수 있다는 함정이 존재합니다 [17].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,23 @@
# [[Concurrent Rendering]]
## 📌 Brief Summary
Concurrent Rendering(동시성 렌더링)은 메인 스레드를 블로킹하지 않고 UI의 여러 부분을 병렬로 렌더링할 수 있게 해주는 React의 핵심 아키텍처 기능입니다 [1]. 렌더링 작업을 'Time Slicing(시간 분할)'을 통해 작은 단위로 쪼개고 중요도에 따라 우선순위를 부여하여, 긴급한 사용자 입력에 반응하기 위해 렌더링을 일시 중지하거나 재개할 수 있습니다 [1, 2]. 이를 통해 무거운 연산 중에도 UI가 멈추지 않고 즉각적으로 반응하도록 하여 애플리케이션의 체감 성능을 극대화합니다 [3, 4].
## 📖 Core Content
* **Fiber 아키텍처와 Work Loop**
Concurrent Rendering은 React 16에서 처음 도입된 Fiber 아키텍처를 기반으로 작동합니다 [5, 6]. 기존의 단일 재귀 호출 기반 동기식 렌더링과 달리, 렌더링 작업을 'Fiber 노드'라는 작은 작업 단위(Unit of Work)로 분할합니다 [2, 7]. React는 Work Loop를 통해 이 트리를 점진적으로 순회하며, 각 작업 단위가 끝날 때마다 브라우저에 제어권을 양보(yield)하여 클릭과 같은 고우선순위 상호작용을 처리할 수 있는지 확인합니다 [8, 9].
* **우선순위 기반 스케줄링 (Lane Model)**
동시성 작업의 우선순위는 'Lane'이라는 비트마스크 시스템을 통해 체계적으로 관리됩니다 [10, 11]. 타이핑이나 클릭처럼 사용자가 즉각적인 반응을 기대하는 긴급한 업데이트(Sync Lane)는 최우선으로 즉시 처리되며, 스크롤(InputContinuous Lane), 네트워크 응답(Default Lane), 백그라운드 렌더링(Idle Lane) 등은 각각 낮은 우선순위를 부여받아 스케줄링됩니다 [12-14]. 이 과정에서 렌더링 단계(Render phase)는 중단 가능(Interruptible)하므로, 더 높은 우선순위의 작업이 도착하면 기존의 렌더링 작업을 일시 중지, 폐기 또는 재시작할 수 있습니다 [15, 16].
* **Concurrent Hooks 활용 (`useTransition`, `useDeferredValue`)**
React 18 및 19에서는 개발자가 동시성 렌더링을 직접 제어할 수 있는 훅을 제공합니다 [17, 18]. **`useTransition`**은 개발자가 상태 업데이트를 직접 긴급하지 않은 것(low-priority)으로 지정하여, 수천 개의 데이터 필터링 연산이 백그라운드에서 도는 중에도 사용자의 타이핑 입력이 즉시 반영되도록 돕습니다 [17, 19, 20]. **`useDeferredValue`**는 외부에서 전달받는 값 자체의 렌더링을 지연시켜, 새로운 결과가 준비될 때까지 UI가 동결되는 것을 막고 이전 결과를 표시하게 해줍니다 [19, 21].
* **성능 최적화 메커니즘 (체감 성능 향상)**
Concurrent Rendering의 핵심은 코드의 실제 연산 속도를 물리적으로 가속하는 것이 아닙니다 [3]. 무거운 연산이 즉각적인 사용자 피드백을 방해하지 않도록 처리 순서를 최적화하여 앱이 **"더 빠르게 느껴지게(feel faster)"** 만드는 데 목적이 있습니다 [3]. 이러한 비차단형(Non-Blocking) 렌더링 방식은 사용자의 입력이 다음 화면 페인트로 이어지는 속도를 측정하는 핵심 웹 지표인 **INP(Interaction to Next Paint)**를 향상시키는 데 직접적으로 기여합니다 [21, 22].
## 🔗 Knowledge Connections
- **Related Topics:** `[[Fiber Architecture]]`, `[[Time Slicing]]`, `[[Lane Model]]`, `[[useTransition]]`, `[[useDeferredValue]]`
- **Projects/Contexts:** `[[React 18 & 19 Performance Optimization]]`
- **Contradictions/Notes:** 소스에 따르면 `useTransition``useDeferredValue`와 같은 동시성 훅은 코드 자체의 속도를 높여주지는 않지만, 무거운 연산이 사용자 피드백을 방해하지 않도록 스케줄링하여 앱의 "체감 성능"을 개선하는 방식으로 작동한다는 점을 명확히 하고 있습니다 [3].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,20 @@
# [[Critical Rendering Path]]
## 📌 Brief Summary
Critical Rendering Path (CRP)는 브라우저가 HTML, CSS, JavaScript를 수신하여 화면의 픽셀로 변환하기 위해 거치는 일련의 단계적 과정을 의미합니다[1]. 이 과정은 DOM 트리 및 CSSOM 트리 구축, Render Tree 합성, Layout(Reflow), 그리고 Paint(Repaint) 및 Compositing 단계로 진행됩니다[1, 2]. CRP를 이해하고 최적화하는 것은 렌더링 차단 요소를 줄이고 불필요한 Reflow 및 Repaint를 최소화하여 빠른 초기 렌더링과 매끄러운 사용자 상호작용을 보장하는 프론트엔드 성능 엔지니어링의 핵심입니다[3, 4].
## 📖 Core Content
* **DOM (Document Object Model) 구축:** 브라우저는 서버로부터 HTML 데이터를 점진적으로 파싱하여 DOM 트리를 구축합니다[2, 5]. 수신된 바이트는 토큰 및 노드로 변환되어 계층 구조를 형성하며, 노드의 수가 많을수록 이후 렌더링 경로의 연산 시간이 길어집니다[2, 5, 6].
* **CSSOM (CSS Object Model) 구축:** DOM과 달리 CSSOM 구축은 점진적으로 이루어지지 않으며, 파싱이 완료될 때까지 렌더링을 차단(Render-blocking)합니다[6-8]. 이는 스타일이 뒤늦게 덮어씌워지면서 스타일이 적용되지 않은 콘텐츠가 화면에 번쩍이는 현상(FOUC)을 방지하기 위함입니다[6, 7].
* **Render Tree 합성:** DOM과 CSSOM이 완성되면, 브라우저는 이 둘을 결합해 화면에 실제로 그려지는 가시적 노드(Visible nodes)만 포함하는 Render Tree를 만듭니다[9-11]. `<script>`, `<meta>` 요소나 `display: none` 스타일이 적용된 노드는 렌더 트리에서 완전히 제외되지만, 레이아웃 공간을 차지하는 `visibility: hidden` 요소는 포함됩니다[9-12].
* **Layout (Reflow):** Render Tree를 기반으로 뷰포트 크기와 박스 모델에 맞춰 각 요소의 정확한 기하학적 위치와 크기를 계산하는 단계입니다[13-15]. 창 크기가 변하거나, DOM 요소의 추가/제거, 혹은 너비나 여백 등 레이아웃에 영향을 주는 속성이 변경될 경우 Reflow가 발생하며 이는 매우 큰 연산 비용을 수반합니다[16-19].
* **Paint (Repaint) 및 Compositing:** Layout 계산이 끝나면 각 요소를 픽셀로 화면에 그리는 Paint(또는 Rasterizing) 과정이 진행됩니다[20-23]. 레이아웃 변화 없이 배경색 등 시각적 속성만 변할 때는 Repaint만 촉발됩니다[18, 20, 24]. 이후 서로 다른 레이어들을 하나의 화면으로 합치는 Compositing 단계를 거치며, 특정 효과(예: transform)는 GPU로 오프로드하여 성능을 최적화할 수 있습니다[20, 25].
* **React 도입과의 연관성:** 전통적으로 브라우저의 DOM을 직접 조작하는 것은 필연적으로 비용이 큰 Reflow와 Repaint 과정을 연쇄적으로 유발하여 속도 저하를 일으킵니다[26]. React는 이 한계를 극복하기 위해 메모리에 경량화된 Virtual DOM을 구축하고, 상태 변경 시 휴리스틱 Diffing 알고리즘(Reconciliation)을 통해 변경된 최소한의 노드만 실제 DOM에 반영하여 렌더링 경로의 비효율을 크게 줄입니다[3, 26, 27].
## 🔗 Knowledge Connections
- **Related Topics:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[Reflow / Repaint 최소화 방법]], [[DOM vs Virtual DOM]]
- **Projects/Contexts:** [[렌더링 최적화 개념 설명 자료]], [[“React가 빠른 이유”]]
- **Contradictions/Notes:** CSS 선택자(Selector)의 복잡도는 파싱 속도에 영향을 주지만, 최신 브라우저 엔진은 매우 빠르기 때문에 선택자 구체성을 최적화해서 얻는 성능적 이득은 마이크로초 단위에 불과합니다. 따라서 실질적인 최적화를 위해서는 선택자 구조 개선보다는 불필요한 렌더링 차단 리소스 크기를 줄이거나 로딩 순서를 제어하는 것이 성능 개선(CRP 최적화)에 훨씬 효과적입니다[28, 29].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,36 @@
# [[DOM vs Virtual DOM]]
## 📌 Brief Summary
DOM(문서 객체 모델)은 브라우저가 HTML을 파싱하여 생성하는 트리 구조로, 직접적인 DOM 조작은 렌더링 경로(레이아웃 및 페인트)를 매번 트리거하여 성능 저하를 유발합니다 [1, 2]. 반면 Virtual DOM(가상 DOM)은 React가 수동적인 DOM 조작의 비효율성을 해결하기 위해 도입한 개념으로, UI의 이상적인 상태를 메모리에 가벼운 JavaScript 객체 형태로 저장하는 방식입니다 [2-4]. React는 새로운 Virtual DOM과 이전 버전을 비교(Diffing)하여 실제 변경된 부분만 실제 DOM에 반영(Reconciliation)함으로써 브라우저의 리플로우와 리페인트를 최소화하고 렌더링 성능을 최적화합니다 [3-5].
## 📖 Core Content
* **DOM(Document Object Model)의 특성과 한계**
* 브라우저는 수신된 HTML 바이트를 문자, 토큰, 노드로 변환하여 점진적으로 DOM 트리를 구축합니다 [1].
* DOM은 페이지의 구조와 콘텐츠를 나타내며, 노드 수가 많고 트리의 깊이가 깊을수록 브라우저의 레이아웃(Reflow) 및 페인트(Repaint) 등 중요 렌더링 경로(Critical Rendering Path) 작업에 걸리는 연산 부담이 증가합니다 [6, 7].
* 웹 애플리케이션에서 DOM을 직접 수정하는 작업은 본질적으로 느립니다 [2]. DOM의 변경은 레이아웃과 페인트 단계를 트리거하며, 여러 노드를 개별적으로 업데이트할 경우 중복된 재계산을 유발하기 때문입니다 [2].
* **Virtual DOM의 개념 및 도입 목적**
* 수동적인 DOM 조작이 가진 비효율성을 추상화하기 위해 React에서 도입한 아키텍처가 Virtual DOM입니다 [2].
* 이는 UI를 메모리 내에 가벼운 JavaScript 객체 형태로 유지하는 표현 방식입니다 [2, 3].
* 개발자가 UI의 이상적인 상태를 선언적으로 정의하면, React(ReactDOM 등)가 실제 DOM을 해당 상태와 일치하도록 알아서 동기화하므로, 개발자는 속성 조작이나 이벤트 처리, 수동적인 DOM 업데이트 등을 직접 처리할 필요가 없습니다 [4].
* Virtual DOM 트리는 설계상 불변(immutable) 객체로 취급됩니다 [8].
* **재조정(Reconciliation)과 Diffing 알고리즘**
* 상태나 속성(props)이 업데이트되면 React는 새로운 Virtual DOM 트리를 생성하고, 이를 이전 버전의 트리와 비교(Diffing)하여 실제 DOM을 가장 효율적으로 업데이트할 방법을 결정합니다 [2, 3, 9]. 이 동기화 과정을 재조정(Reconciliation)이라고 합니다 [3, 4].
* 두 트리를 비교하는 일반적인 알고리즘은 $O(n^3)$의 복잡도를 가져, 요소가 많아질 경우 실시간 연산에 부적합할 만큼 비용이 큽니다 [9-11].
* 대신 React는 두 가지 가정을 기반으로 $O(n)$ 복잡도의 휴리스틱 Diffing 알고리즘을 사용합니다 [10, 11].
1. 서로 다른 타입의 요소는 전혀 다른 트리를 생성한다고 가정하여 기존 트리를 허물고 완전히 새로 구축합니다 [10-12].
2. 개발자가 제공하는 `key` 속성을 통해 여러 렌더링에 걸쳐 안정적으로 유지되는 자식 요소가 무엇인지 식별합니다 [10, 11].
* 이러한 접근 방식을 통해 React는 변경된 특정 속성이나 노드만을 수정하고, 기본 DOM 노드와 상태를 가능한 한 보존하여 효율성을 높입니다 [13-15].
* **성능 최적화 관점 (React가 빠른 이유)**
* Virtual DOM은 일시적인 프레젠테이션 상태를 지속적인 애플리케이션 상태와 분리하고 변경되지 않은 프레젠테이션 상태를 보존함으로써, 브라우저의 무거운 DOM 연산을 줄이고 UI 렌더링 성능을 개선합니다 [3].
* 그러나 Virtual DOM의 Diffing 작업 자체가 연산 비용이 전혀 없는 것은 아닙니다 [16]. Virtual DOM은 실제 DOM이 업데이트될 필요가 없는 경우는 잘 잡아내지만, 부모 컴포넌트의 상태 변경으로 인해 하위 컴포넌트 전체가 재렌더링되는 폭포수 현상(Re-Render Cascade)이 발생하면 불필요한 Diffing 연산이 낭비될 수 있습니다 [16, 17]. 이를 최소화하려면 `React.memo` 등을 통해 선택적으로 리렌더링을 차단하는 최적화가 병행되어야 합니다 [16].
## 🔗 Knowledge Connections
- **Related Topics:** [[Critical Rendering Path]], [[Reflow and Repaint]], [[Reconciliation]], [[React Fiber Architecture]]
- **Projects/Contexts:** [[프론트엔드 기초 구조 이해]], [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[“React가 빠른 이유” 및 렌더링 최적화 개념]]
- **Contradictions/Notes:** Virtual DOM이 수동 DOM 조작 비용을 크게 줄여주어 React의 빠른 성능을 보장하지만, 소스에 따르면 "Virtual DOM의 Diffing 작업 자체가 무료는 아니며(not free), 무분별한 리렌더링 폭포수(Re-Render Cascade)가 발생할 경우 연산 낭비와 성능 저하의 주원인이 될 수 있다"고 경고합니다 [16]. 따라서 완벽한 성능을 위해서는 Virtual DOM에만 의존하지 않고 메모이제이션(Memoization)을 통한 컴포넌트 최적화가 필요합니다 [16].
---
*Last updated: 2026-04-25*
+19
View File
@@ -0,0 +1,19 @@
# [[DOM]]
## 📌 Brief Summary
DOM(Document Object Model)은 브라우저가 수신한 HTML 문서를 구문 분석하여 구성하는 문서의 구조와 콘텐츠를 나타내는 계층적 트리 구조입니다 [1-3]. 이는 브라우저의 렌더링 과정인 크리티컬 렌더링 패스(CRP)에서 CSSOM과 결합하여 화면에 그려질 렌더 트리(Render Tree)를 생성하는 핵심 기초가 됩니다 [4-6]. JavaScript를 통한 직접적인 DOM 조작은 레이아웃(Reflow)과 페인트 작업을 유발해 성능을 저하시키므로, 최신 프레임워크인 React는 이를 최적화하기 위해 Virtual DOM을 활용합니다 [7].
## 📖 Core Content
* **DOM 트리의 점진적 구축:** 브라우저는 HTML 응답을 받으면 바이트(bytes)를 문자, 토큰(token), 노드(node)로 변환하는 과정을 거쳐 DOM 트리를 구성합니다 [3, 8, 9]. HTML의 시작 태그와 종료 태그는 노드 간의 부모, 자식, 형제 관계와 같은 계층 구조를 정의하며, `<html>` 요소가 문서 트리의 루트 노드가 됩니다 [3, 9]. DOM의 구축은 점진적(incremental)으로 이루어지기 때문에, 브라우저는 데이터를 수신하는 도중에도 트리를 구축할 수 있습니다 [8, 9].
* **렌더 트리(Render Tree)의 형성:** DOM은 페이지의 '콘텐츠'를 담고 있으며, 페이지의 '스타일'을 담고 있는 CSSOM(CSS Object Model)과 결합하여 렌더 트리를 완성합니다 [5, 6, 10, 11]. 이 렌더 트리는 화면에 실제로 그려지는 가시적인 노드만을 포함하며, `<head>` 태그나 `display: none` 스타일이 적용된 DOM 노드는 렌더 트리에 포함되지 않습니다 [4, 5, 12, 13].
* **DOM 조작과 렌더링 성능(Reflow & Repaint):** DOM 노드의 수가 많고 깊이가 깊을수록 레이아웃 및 페인트와 같은 후속 렌더링 단계에 걸리는 연산 부담이 크게 증가합니다 [2, 3, 10, 14]. 또한, JavaScript로 DOM의 구조를 추가/삭제하거나 크기, 위치 속성을 변경하면 브라우저는 화면의 레이아웃을 다시 계산하는 Reflow(또는 Layout)를 실행하고, 이어 픽셀을 다시 그리는 Repaint 단계를 거치게 되어 막대한 연산 비용이 발생합니다 [7, 14-17].
* **성능 최적화 및 접근 최소화 방법:** DOM 조작으로 인한 성능 저하를 막기 위해 DOM 노드나 속성값을 변수에 캐싱(Caching)하여 재사용하거나, 연산을 반복문 외부로 빼내어 DOM 상호작용 횟수를 최소화해야 합니다 [18, 19]. 특히, DOM 값을 읽는 작업(Phase 1)과 수정하는 작업(Phase 2)을 교차로 수행하는 레이아웃 스래싱(Layout thrashing)을 방지하도록 코드를 분리하는 것이 중요합니다 [19-21].
* **React의 Virtual DOM 도입 배경:** 위와 같은 직접적인 DOM 조작의 비효율성을 극복하기 위해 React는 메모리상에 존재하는 가벼운 복사본인 Virtual DOM(VDOM)을 도입했습니다 [7, 22]. 상태가 변경되면 React는 새로운 Virtual DOM을 생성하고 이전과 비교(Diffing/Reconciliation)하여 변경된 최소한의 부분만을 실제 DOM에 반영함으로써 렌더링 성능을 극대화합니다 [7, 22, 23].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[CSSOM]], [[Render Tree]], [[Reflow 및 Repaint]], [[Critical Rendering Path (CRP)]]
- **Projects/Contexts:** [[React 렌더링 최적화]], [[브라우저 렌더링 과정]], [[웹 성능 가이드(Web Performance)]]
- **Contradictions/Notes:** DOM의 구축은 HTML 데이터를 수신함과 동시에 '점진적(incremental)'으로 이루어지며 렌더링을 차단하지 않는 반면, 스타일을 정의하는 CSSOM의 구축은 후속 규칙이 이전 규칙을 덮어쓸 수 있기 때문에 완전히 구문 분석될 때까지 렌더링을 차단(render-blocking)한다는 점에서 작동 방식의 차이가 있습니다 [2, 8-10].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,27 @@
# [[Diffing Algorithm]]
## 📌 Brief Summary
Diffing Algorithm(디핑 알고리즘)은 React에서 이전 가상 DOM(Virtual DOM) 트리와 새롭게 계산된 트리를 비교하여 실제 DOM을 가장 효율적으로 업데이트할 방법을 결정하는 과정입니다 [1, 2]. 이론적인 트리 비교 알고리즘은 $O(n^3)$의 시간 복잡도를 가져 실시간 애플리케이션에 부적합하지만, React는 두 가지 휴리스틱 가정을 통해 이를 $O(n)$ 복잡도로 최적화했습니다 [3-5]. 이 알고리즘은 'Reconciliation(재조정)' 과정의 핵심으로, 불필요한 DOM 조작을 최소화하여 렌더링 성능을 극대화하는 역할을 합니다 [1, 2, 6].
## 📖 Core Content
* **알고리즘의 기본 원리 및 가정:**
React의 디핑 알고리즘은 두 가지 주요 가정에 기반하여 $O(n)$의 성능을 달성합니다. 첫째, 서로 다른 타입의 요소는 근본적으로 다른 트리를 생성한다고 가정합니다 [3, 5]. 둘째, 개발자가 제공하는 `key` prop을 통해 여러 렌더링 사이클 동안 안정적으로 유지되는 자식 요소를 식별할 수 있다고 가정합니다 [3, 5].
* **비교(Diffing) 프로세스 메커니즘:**
* **다른 타입의 요소:** 루트 요소의 타입이 다를 경우(예: `<a>`에서 `<img>`로 변경), React는 이전 트리를 완전히 허물고 처음부터 새로운 트리를 구축합니다. 이 과정에서 기존 DOM 노드와 연관된 컴포넌트의 상태(State)는 모두 파괴됩니다 [7, 8].
* **동일한 타입의 DOM 요소:** 두 요소의 속성을 비교하여 동일한 기본 DOM 노드를 유지한 채 변경된 속성(예: `className`, `color``fontWeight` 같은 `style` 등)만 업데이트합니다 [9, 10].
* **동일한 타입의 컴포넌트 요소:** 컴포넌트의 인스턴스가 동일하게 유지되어 상태가 보존됩니다. 새로운 요소에 맞게 prop이 업데이트된 후, 하위 요소들에 대해 재귀적으로 디핑 알고리즘을 수행합니다 [10, 11].
* **자식 요소의 재귀적 처리와 Key의 역할:**
기본적으로 React는 두 하위 요소 목록을 동시에 반복하면서 차이가 있을 때마다 변이를 생성합니다 [11]. 하지만 리스트의 맨 앞에 요소를 추가하는 경우 등 순서가 변경될 때는 전체를 다시 렌더링하는 매우 비효율적인 상황이 발생할 수 있습니다 [12]. 이를 해결하기 위해 고유한 `key` 속성을 사용하면, React는 기존 트리와 새 트리의 자식들을 일치시켜 이동한 요소만 파악하므로 불필요한 DOM 재생성을 방지할 수 있습니다 [12, 13].
* **트레이드오프 및 주의사항:**
이 알고리즘은 휴리스틱에 의존하기 때문에 가정이 충족되지 않으면 성능이 저하될 수 있습니다 [14]. 예를 들어 하위 트리가 형제 요소 사이가 아닌 아예 다른 계층으로 이동하는 경우, 알고리즘은 해당 하위 트리를 완전히 다시 렌더링합니다 [15]. 또한 배열의 인덱스를 키로 사용하거나 `Math.random()` 같은 불안정한 키를 사용하면 리스트가 재정렬될 때 컴포넌트 상태가 꼬이거나 성능 저하가 발생할 수 있습니다 [14, 16].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[React Fiber]]
- **Projects/Contexts:** [[React Frontend Development]], [[Component-Based Architecture]]
- **Contradictions/Notes:** 일반적인 트리 비교 알고리즘은 $O(n^3)$의 복잡도를 가지지만, React의 디핑 알고리즘은 휴리스틱(Heuristics)을 적용하여 실용적인 $O(n)$ 복잡도로 구현되었다는 점이 핵심적인 기술적 차이입니다 [4, 5]. 배열의 인덱스를 `key`로 사용하는 것은 요소의 순서가 변경되지 않을 때만 유효하며, 재정렬(Reorder) 시에는 비효율적이고 상태 오류를 일으킬 수 있으므로 권장되지 않습니다 [13, 16].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,24 @@
# [[Fiber Architecture]]
## 📌 Brief Summary
React 16에서 도입된 Fiber Architecture는 동시성 렌더링(Concurrent Rendering)을 지원하기 위해 근본적으로 재작성된 React의 재조정(Reconciliation) 엔진입니다 [1-3]. 기존의 동기식 렌더링이 메인 스레드를 차단하여 UI가 멈추던 문제를 해결하고자, 렌더링 작업을 '파이버(Fiber)'라는 작은 단위의 노드로 쪼개어 점진적으로 처리합니다 [4, 5]. 이를 통해 React는 렌더링을 일시 중지하거나 브라우저에 제어권을 양보하고, 우선순위가 높은 작업을 먼저 처리한 후 다시 렌더링을 재개하는 타임 슬라이싱(Time-slicing) 스케줄링을 구현할 수 있게 되었습니다 [4-6].
## 📖 Core Content
* **동기식 차단(Synchronous Blocking)의 한계 극복:**
Fiber 도입 이전의 React는 '스택 재조정자(Stack Reconciler)'를 사용하여 전체 컴포넌트 트리를 단일 재귀 호출로 동기 처리했습니다 [4]. 이 방식은 대규모 애플리케이션에서 브라우저의 프레임 예산(16.6ms)을 초과할 경우 메인 스레드를 차단하여 사용자 입력이나 애니메이션을 지연시켰습니다 [4]. Fiber는 작업을 작은 단위로 나누어 브라우저가 높은 우선순위의 작업을 가로채 처리할 수 있게 함으로써 이 문제를 해결합니다 [4, 5, 7].
* **작업 루프(Work Loop)와 두 가지 렌더링 단계:**
Fiber의 재조정 과정은 작업 중단과 우선순위 관리를 위해 두 가지 명확한 단계로 나뉩니다 [8].
* **렌더링 단계 (Render Phase):** 이 단계는 비동기적이며 중단할 수 있습니다 [8]. 실제 DOM을 변경하지 않고 메모리 상의 파이버 트리를 순회하면서 이전 상태와 새로운 상태의 차이를 계산하고, 변경이 필요한 파이버들의 목록(Effect list)을 구성합니다 [8, 9]. 더 높은 우선순위 작업이 들어오면 일시 중단, 폐기 또는 재시작될 수 있으므로, 이 단계에서는 사이드 이펙트가 발생해서는 안 됩니다 [8-10].
* **커밋 단계 (Commit Phase):** 이 단계는 동기적이며 중단할 수 없습니다 [11]. 렌더링 단계에서 만들어진 변경 사항(삽입, 삭제, 업데이트)을 한 번에 실제 DOM에 적용합니다 [9, 11, 12]. 이 시점에 실제 DOM이 변형되며 각종 생명주기 메서드나 레이아웃 이펙트(`useLayoutEffect`)가 실행됩니다 [11, 12].
* **레인(Lane) 모델을 통한 우선순위 스케줄링:**
Fiber는 32비트 정수 비트마스크 시스템인 '레인(Lane)'을 사용하여 작업의 우선순위를 정밀하게 관리합니다 [13, 14]. 클릭이나 타이핑 등 즉각적 반응이 필요한 작업(Sync Lane), 스크롤링(InputContinuous Lane), 일반적인 상태 업데이트(Default Lane), 백그라운드 작업(Idle Lane)으로 업데이트를 분류합니다 [6, 15]. 이를 통해 사용자 상호작용과 같은 '긴급한' 업데이트가 데이터 렌더링 같은 '비긴급' UI 전환보다 먼저 처리되도록 보장합니다 [6, 16].
* **작업 진행 상태(WIP) 트리 관리:**
React는 현재 화면에 그려진 상태를 추적할 뿐만 아니라 작업 중인 상태를 나타내는 WIP(Work-in-progress) 트리를 별도로 관리합니다 [10]. 스케줄러의 우선순위에 따라 메인 스레드가 바쁘면 이 WIP 트리의 작업을 일시 중지하고, 브라우저가 유휴 상태일 때 다시 재개할 수 있습니다 [10].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[Concurrent Rendering]], [[Critical Rendering Path]]
- **Projects/Contexts:** [[React 16+ Core Engine]], [[브라우저 메인 스레드 최적화 및 타임 슬라이싱]]
- **Contradictions/Notes:** Fiber의 동시성 렌더링 기능(예: `useTransition`, `useDeferredValue`)은 코드의 물리적인 실행 속도를 높이는 것은 아닙니다 [17]. 무거운 연산으로 인한 병목이 즉각적인 사용자 상호작용을 방해하지 않도록 뒤로 미룸(Deferring)으로써, 체감 성능(Perceived Performance) 측면에서 애플리케이션이 훨씬 "더 빠르게 느껴지도록" 만드는 것이 핵심입니다 [17].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[Hydration]]
## 📌 Brief Summary
Hydration은 서버에서 생성된 정적 HTML을 클라이언트에서 JavaScript를 통해 완전히 상호작용 가능한 애플리케이션으로 변환하는 과정입니다 [1]. 브라우저가 서버로부터 미리 렌더링된 HTML을 받아 화면에 표시한 후, 다운로드한 JavaScript 번들을 실행하여 이벤트 리스너를 연결하고 상태(state)를 동기화합니다 [2, 3]. 이 과정을 거쳐야만 사용자가 정적인 뼈대(Skeleton) 화면을 넘어 버튼 클릭이나 폼 입력 등의 동적 상호작용을 수행할 수 있게 됩니다 [1, 4].
## 📖 Core Content
* **Hydration의 작동 원리 및 역할:**
SSR(Server-Side Rendering) 환경에서 서버는 데이터가 포함된 완전한 HTML을 브라우저로 전송합니다 [2]. 브라우저는 이를 즉시 화면에 렌더링하여 사용자에게 보여주지만(빠른 콘텐츠 표시), JavaScript 번들이 다운로드, 파싱 및 Hydration 되기 전까지는 페이지가 상호작용하지 않습니다 [2, 5]. 즉, Hydration은 서버가 제공한 건조한(Dehydrated) HTML 컴포넌트에 생명을 불어넣어 반응형으로 만드는 필수 단계입니다 [1, 6].
* **성능에 미치는 부정적 영향:**
기본적으로 React는 화면에 보이지 않는 요소까지 포함하여 전체 페이지를 한 번에 Hydration 하려고 시도합니다 [7]. 이로 인해 불필요한 JavaScript 실행이 발생하여 메인 스레드(Main Thread)가 차단되고, 결과적으로 TBT(Total Blocking Time), FID(First Input Delay), TTI(Time to Interactive)와 같은 핵심 성능 지표가 악화될 수 있습니다 [7, 8]. 시각적 요소는 렌더링되었으나 클릭해도 반응하지 않는 지연 현상이 발생하여 사용자 경험(UX)에 악영향을 미치기도 합니다 [5, 7].
* **주요 문제 및 발생 원인:**
* **Hydration 에러 (Mismatch):** 서버에서 렌더링된 HTML과 클라이언트 렌더링 결과가 일치하지 않을 때 발생합니다. 주로 환경 조건에 따른 렌더링 차이, 시간 의존적 데이터 변화, 서드파티 라이브러리의 DOM 조작 등이 원인입니다 [9].
* **번들 크기 비대화:** Hydration을 위해서는 모든 컴포넌트의 JavaScript 코드가 필요하므로, 번들 크기가 커져 다운로드 및 실행 오버헤드가 증가합니다 [10].
* **Hydration 최적화 전략:**
* **선택적 및 점진적 Hydration (Selective & Progressive Hydration):** `next/dynamic`과 같은 동적 임포트를 사용하여 중요하지 않은 컴포넌트의 Hydration을 지연시키고 화면 위쪽(Above-the-fold) 콘텐츠를 우선 처리합니다 [10, 11]. React 18의 동시성 렌더링(Concurrent Rendering)은 사용자가 상호작용하는 부분을 우선적으로 Hydration 할 수 있도록 지원합니다 [12].
* **뷰포트 기반 지연 (Lazy Hydration):** `IntersectionObserver` API 등을 활용하여 컴포넌트가 화면에 보일 때만 Hydration을 수행함으로써 초기 TBT를 대폭 줄입니다 [11].
* **React Server Components (RSC) 도입:** 서버 컴포넌트는 오직 서버에서만 실행되며 클라이언트로 JavaScript를 전송하지 않습니다. 따라서 상호작용이 필요 없는 정적 UI의 경우 Hydration 과정 자체가 필요 없어 번들 크기 및 실행 오버헤드를 근본적으로 제거할 수 있습니다 [13, 14].
## 🔗 Knowledge Connections
- **Related Topics:** [[Server-Side Rendering (SSR)]], [[React Server Components (RSC)]], [[Time to Interactive (TTI)]], [[Total Blocking Time (TBT)]]
- **Projects/Contexts:** [[Next.js 렌더링 최적화]], [[React 18 동시성 렌더링 (Concurrent Rendering)]]
- **Contradictions/Notes:** SSR은 초기 콘텐츠를 즉시 렌더링하여 SEO와 FCP(First Contentful Paint)를 향상시키는 장점이 있지만, Hydration 완료 전까지 페이지 조작이 불가능하여 TTI가 지연된다는 뚜렷한 트레이드오프가 존재합니다 [5, 15, 16]. 그러나 React Server Components(RSC)나 선택적 Hydration 기법을 활용하면 인터랙티브한 부분에만 클라이언트 코드를 적용할 수 있어 이러한 SSR의 한계를 상쇄할 수 있습니다 [12, 17].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,19 @@
# [[Next.js 렌더링 최적화]]
## 📌 Brief Summary
Next.js 렌더링 최적화는 애플리케이션의 성능, SEO 및 사용자 경험을 극대화하기 위해 페이지 특성에 맞춰 다양한 렌더링 전략(SSR, SSG, CSR, ISR)을 조합하여 사용하는 과정을 의미합니다 [1-3]. 특히 React Server Components(RSC)를 활용하여 서버에서 렌더링과 데이터 페칭을 처리함으로써 클라이언트로 전송되는 자바스크립트 번들의 크기를 대폭 줄입니다 [4, 5]. 이를 통해 초기 로딩 속도(LCP)를 개선하고 부드러운 상호작용을 보장하는 것이 핵심 목적입니다 [6-8].
## 📖 Core Content
- **하이브리드 렌더링 전략 (Hybrid Rendering):** Next.js는 동일한 애플리케이션 내에서 페이지별 요구사항에 따라 렌더링 방식을 유연하게 혼합할 수 있습니다 [1, 2]. 마케팅 페이지나 공식 문서에는 정적 사이트 생성(SSG)을, 항상 최신 상태를 유지해야 하는 상품 페이지에는 서버 사이드 렌더링(SSR)을, 사용자 대시보드와 같이 인터랙션이 중요한 곳에는 클라이언트 사이드 렌더링(CSR)을 적용하여 성능과 SEO를 최적화합니다 [1, 3].
- **점진적 정적 재생성 (ISR):** 정적 생성(SSG)의 압도적인 로딩 속도와 SSR의 데이터 최신화 이점을 결합한 모델입니다 [9, 10]. 전체 사이트를 다시 빌드할 필요 없이 특정 시간 간격이나 요청에 따라 백그라운드에서 개별 정적 페이지를 업데이트하여 최신 상태의 캐시된 콘텐츠를 제공합니다 [10-12].
- **React Server Components (RSC) 생태계 도입:** Next.js의 App Router는 기본적으로 컴포넌트를 서버 컴포넌트로 처리합니다 [13]. 정적인 UI는 서버에서 렌더링 되어 HTML과 직렬화된 명령(React Flight 프로토콜)으로만 전달되며, 브라우저로 전송되는 자바스크립트(0 bytes)를 줄여 성능을 크게 향상시킵니다 [4, 5, 14-16]. 인터랙션이 필수적인 부분만 `"use client"` 지시어를 사용해 클라이언트 컴포넌트로 분리합니다 [14, 17, 18].
- **데이터 페칭과 병렬 처리:** 서버 컴포넌트를 사용하면 API 계층을 거칠 필요 없이 데이터베이스나 로컬 파일 시스템에서 직접 데이터를 가져올 수 있습니다 [14, 19, 20]. 이를 적절히 설계하면 렌더링 중 부모와 자식 컴포넌트가 독립적으로 데이터를 병렬 호출할 수 있어, 네트워크 워터폴(Waterfall) 현상을 제거하고 응답 속도를 최소화합니다 [21, 22].
- **자동화된 최적화 도구 활용:** `next/image` 컴포넌트는 이미지 포맷 자동 변환(WebP/AVIF), 반응형 사이징, 그리고 화면에 보일 때만 이미지를 로드하는 지연 로딩(Lazy Loading)을 지원하여 Core Web Vitals를 향상시킵니다 [7, 23, 24]. 추가로 최신 Next.js 환경에서는 React Compiler를 설정하여 수동 메모이제이션 없이 렌더링 최적화를 자동화할 수도 있습니다 [25].
## 🔗 Knowledge Connections
- **Related Topics:** [[React Server Components]], [[점진적 정적 재생성 (ISR)]], [[하이드레이션 (Hydration)]]
- **Projects/Contexts:** [[Next.js App Router]], [[전자상거래 플랫폼 (E-commerce Platforms)]]
- **Contradictions/Notes:** SSR은 초기 콘텐츠 렌더링(FCP)이 빠르고 SEO에 매우 유리하지만, 자바스크립트를 로드하고 연결하는 '하이드레이션(Hydration)' 과정을 거쳐야 하므로 사용자가 페이지와 상호작용하기까지의 시간(TTI)이 지연될 수 있습니다 [8, 26-28]. 또한, 서버 컴포넌트를 사용하더라도 데이터 의존성이 직렬(Sequential)로 연결되어 있다면 브라우저가 아닌 서버 측에서 워터폴 현상이 발생해 응답 지연이 생길 수 있으므로 병렬 처리를 고려한 설계가 필요합니다 [29, 30].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[React 18 동시성 렌더링 (Concurrent Rendering)]]
## 📌 Brief Summary
React 18 동시성 렌더링(Concurrent Rendering)은 React가 렌더링 작업을 여러 단위로 나누고, 작업의 우선순위를 평가하여 브라우저의 메인 스레드를 차단하지 않고 UI를 부드럽게 업데이트할 수 있도록 설계된 아키텍처적 패러다임입니다 [1-3]. 이는 Fiber 아키텍처와 스케줄러의 타임 슬라이싱(Time-Slicing) 및 우선순위 레인(Lanes) 시스템을 기반으로 동작합니다 [2, 4, 5]. 이를 통해 개발자는 무거운 데이터 연산 중에도 사용자 입력과 같은 긴급한 상호작용을 즉각적으로 처리하여 애플리케이션의 체감 응답성을 크게 향상시킬 수 있습니다 [6-8].
## 📖 Core Content
* **동기식 블로킹의 한계 극복 (Fiber 아키텍처 도입):**
과거의 React는 한 번 렌더링이 시작되면 전체 컴포넌트 트리가 처리될 때까지 멈출 수 없어, 무거운 작업 시 메인 스레드가 차단되고 UI가 응답하지 않는 문제가 있었습니다 [4]. 이를 해결하기 위해 설계된 Fiber 아키텍처는 렌더링 작업을 'Fiber 노드'라는 단위로 잘게 분할하여, 스케줄러가 여러 프레임에 걸쳐 작업을 점진적으로 분산 처리할 수 있도록 지원합니다 [2].
* **타임 슬라이싱(Time-Slicing)과 렌더링 단계의 분리:**
동시성 렌더링은 타임 슬라이싱을 사용하여 렌더링 작업을 나누고, 필요 시 브라우저에 제어권을 양보(yield)합니다 [4, 9]. 렌더링은 두 가지 단계로 나뉘는데, 변경 사항의 목록을 계산하는 '렌더(Render) 단계'는 언제든 일시 중지, 재개 또는 폐기될 수 있습니다 [10, 11]. 반면 실제 DOM에 변경 사항을 적용하는 '커밋(Commit) 단계'는 동기적이고 중단할 수 없는 형태로 한 번에 실행됩니다 [11-13].
* **우선순위 기반 관리 (Lane 모델):**
React는 비트마스크 시스템을 활용한 'Lanes'라는 모델을 통해 작업의 우선순위를 관리합니다 [14, 15]. 클릭이나 타이핑 같은 긴급한 사용자 입력은 'Sync Lane'으로 분류되어 즉시 처리되며, 화면 외부 렌더링이나 무거운 데이터 필터링은 'Idle Lane' 등의 낮은 우선순위로 분류됩니다 [14, 16]. 이 모델을 통해 진행 중이던 낮은 우선순위 작업은 더 중요한 업데이트가 도착하면 중단되거나 우선순위가 조정될 수 있습니다 [17].
* **동시성 제어를 위한 API (`useTransition`, `useDeferredValue` 등):**
개발자는 React에서 제공하는 훅을 활용해 긴급하지 않은 업데이트를 백그라운드로 지연시킬 수 있습니다 [6]. `startTransition`이나 `useTransition`은 특정 상태 업데이트의 우선순위를 낮추어 사용자 입력 같은 긴급한 작업이 먼저 처리되게 합니다 [6, 18]. 상태 업데이트 코드를 직접 제어할 수 없는 경우(예: props로 값을 전달받는 경우)에는 `useDeferredValue`를 사용하여 렌더링 연산을 지연시킴으로써 UI가 멈추는 것을 방지할 수 있습니다 [19, 20]. 긴급히 동기적으로 업데이트를 강제해야 할 때에는 `flushSync`를 사용할 수 있습니다 [21].
## 🔗 Knowledge Connections
- **Related Topics:** [[React Fiber]], [[Time-Slicing]], [[Lanes Model]], [[Automatic Batching]], [[Virtual DOM]]
- **Projects/Contexts:** [[무거운 데이터 리스트 필터링 구현]], [[타이핑에 즉각 반응해야 하는 검색창 (Search-as-you-type)]]
- **Contradictions/Notes:** 소스 [6]에서는 `useTransition``useDeferredValue` 등 동시성 제어 훅을 "React 19의 기능"으로 설명하고 있으나, 소스 [21]와 [18]에서는 `startTransition``flushSync`를 통한 렌더링 제어가 "React 18에 도입되었다"고 서술합니다. 이는 React 18에서 도입된 동시성 렌더링 기능이 후속 버전에서도 계속 확장 및 핵심 성능 최적화 패턴으로 사용되고 있음을 시사합니다.
---
*Last updated: 2026-04-25*
@@ -0,0 +1,29 @@
# [[React Fiber]]
## 📌 Brief Summary
React Fiber는 React 16에서 도입된 새로운 재조정(Reconciliation) 엔진이자 아키텍처로, 동시성 렌더링(Concurrent Rendering)을 지원하기 위해 개발되었습니다 [1, 2]. 기존의 동기적이고 중단 불가능한 렌더링 방식의 한계를 극복하기 위해 렌더링 작업을 '작은 작업 단위(Fiber node)'로 분할하여 처리합니다 [1, 3, 4]. 이를 통해 메인 스레드를 차단하지 않고 작업의 우선순위를 유연하게 관리하며 렌더링을 일시 중지하거나 재개할 수 있어, 사용자 상호작용에 빠르고 부드럽게 반응하는 UI를 구축할 수 있습니다 [3, 5, 6].
## 📖 Core Content
* **파이버 노드(Fiber Node)와 작업 루프(Work Loop):**
React는 컴포넌트 트리의 각 요소를 파이버 노드로 표현하며, 이는 곧 수행해야 할 개별 '작업 단위(Unit of Work)'가 됩니다 [4, 7]. 파이버 재조정자는 이 작업 단위들을 순차적으로 처리하는 작업 루프를 통해 작동합니다 [4, 8]. 하나의 작업을 처리한 후 남은 프레임 시간을 확인하여, 시간이 부족하거나 고우선순위 작업(예: 사용자 입력)이 대기 중일 경우 브라우저에 제어권을 양보(yield)하여 UI가 멈추는 것을 방지합니다 [5, 9].
* **두 가지 렌더링 단계(Reconciliation Phases):**
React의 재조정 과정은 작업의 중단 및 우선순위 지정을 가능하게 하기 위해 두 가지 페이즈로 나뉩니다 [10].
* **렌더 페이즈(Render Phase):** 중단, 취소, 재개가 가능한 비동기적 단계입니다 [10, 11]. 기존 상태와 새로운 상태의 차이를 계산하고 부수 효과(Effect)를 가진 파이버 노드들의 목록을 구성하지만, 이 단계에서는 실제 DOM을 변경하지 않습니다 [10, 11].
* **커밋 페이즈(Commit Phase):** 동기적이고 중단할 수 없는 단계입니다 [11, 12]. 렌더 페이즈에서 도출된 모든 DOM 조작(삽입, 삭제, 업데이트 등)을 실제 DOM에 한 번에 반영합니다 [12, 13].
* **시간 분할(Time-Slicing)과 레인(Lane) 기반 우선순위 모델:**
* 파이버는 시간 분할 기능을 활성화하여 무거운 렌더링 작업을 작은 덩어리로 쪼개고, 렌더링 중간에 브라우저가 다른 중요한 작업을 처리할 수 있게 합니다 [3, 6, 9].
* 작업의 우선순위를 32비트 정수를 활용한 '레인(Lane)' 모델로 체계적으로 관리합니다 [14, 15]. 타이핑이나 클릭 같은 사용자 입력은 즉시(Sync) 처리되는 가장 높은 우선순위를 갖고, 데이터 페칭 결과나 화면 밖의 렌더링은 상대적으로 낮은 우선순위(Default, Idle)를 갖게 됩니다 [14, 16].
* 이러한 우선순위 분배를 통해 `useTransition`이나 `useDeferredValue` 같은 동시성 렌더링 훅이 UI의 반응성을 유지하면서 무거운 연산을 지연시킬 수 있도록 지원합니다 [17].
* **WIP(Work-In-Progress) 트리 관리:**
React는 현재 진행 중인 렌더링 작업(WIP)을 조건에 따라 일시 중지(Pause), 재개(Resume), 혹은 폐기(Discard)할 수 있습니다 [18]. 메인 스레드가 바쁘거나 더 높은 우선순위의 업데이트가 들어오면 현재 작업을 멈추어 두었다가, 유휴 시간이 생기면 다시 재개하여 컴퓨팅 자원을 효율적으로 사용합니다 [18].
## 🔗 Knowledge Connections
- **Related Topics:** [[Concurrent Rendering]], [[Reconciliation]], [[Virtual DOM]], [[Critical Rendering Path]]
- **Projects/Contexts:** [[브라우저 렌더링 과정 최적화 및 UI 반응성 개선]]
- **Contradictions/Notes:** React Fiber 아키텍처 이전의 React는 "스택 재조정자(Stack Reconciler)"를 사용하여 컴포넌트 트리를 단일 재귀 호출로 처리했기 때문에, 애플리케이션의 크기가 커질 경우 메인 스레드가 차단(Blocking)되어 사용자 입력이나 애니메이션이 끊기는 고질적인 문제가 존재했습니다. Fiber는 이를 작업 단위 분할로 해결했습니다 [1, 3].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,23 @@
# [[React Performance Optimization]]
## 📌 Brief Summary
React 성능 최적화는 브라우저의 렌더링 과정에서 발생하는 레이아웃 계산과 페인팅 비용을 최소화하고, 효과적인 렌더링 전략을 통해 애플리케이션의 반응성을 극대화하는 과정입니다 [1, 2]. 이를 위해 React는 가상 DOM(Virtual DOM)과 휴리스틱 Diffing 알고리즘, 그리고 Fiber 아키텍처를 도입하여 UI 업데이트를 효율적으로 관리합니다 [3-5]. 궁극적으로 개발자는 CSR, SSR, SSG와 같은 렌더링 방식을 서비스의 특성에 맞게 선택하고, 컴포넌트 기반 설계와 최적화 도구를 활용해 사용자 경험을 획기적으로 향상시킬 수 있습니다 [6, 7].
## 📖 Core Content
* **브라우저 렌더링 과정 및 Reflow/Repaint 최소화:** 브라우저는 HTML과 CSS를 파싱하여 DOM과 CSSOM을 각각 생성하고, 이를 결합하여 화면에 표시될 요소만 담은 Render Tree를 구축합니다 [8-11]. 이후 각 요소의 정확한 크기와 위치를 계산하는 Layout(Reflow) 단계와 화면에 픽셀로 변환해 그리는 Paint(Repaint) 단계를 거칩니다 [12-15]. 직접적인 DOM 조작은 연산 비용이 높은 Reflow와 Repaint를 반복적으로 유발해 애플리케이션 성능을 저하시킵니다 [1, 16, 17]. 이를 방지하기 위해 CSS transform 속성을 활용하거나 불필요한 DOM 깊이를 줄이고, 리스트 렌더링 시 가상화 기법을 적용하는 최적화 방법이 권장됩니다 [13, 18-20].
* **DOM vs Virtual DOM과 React의 속도 향상 메커니즘:** React는 실제 DOM을 직접 수정하는 대신, 메모리 내에 가벼운 객체 형태인 Virtual DOM을 유지합니다 [1, 5, 21, 22]. 상태가 변경되면 새로운 Virtual DOM을 만들고, 휴리스틱 기반의 O(n) Diffing 알고리즘을 통해 이전 트리와 비교(Reconciliation)합니다 [3, 5, 23]. 이 알고리즘은 요소의 타입과 Key 속성을 바탕으로 변경된 최소한의 노드만 식별한 뒤 실제 DOM에 일괄 적용하므로, 불필요한 Reflow를 막고 렌더링 성능을 크게 높입니다 [3, 24, 25].
* **React 엔진 최적화 (Fiber 아키텍처 및 최근 기능):** React 16부터 도입된 Fiber 아키텍처는 렌더링 작업을 중단 및 재개 가능한 작은 '작업 단위'로 나누고, 우선순위(Lane 모델)에 따라 처리하는 동시성 렌더링(Concurrent Rendering)을 지원합니다 [4, 26-30]. 또한 React 18에 도입된 자동 일괄 처리(Automatic Batching)는 Promise, setTimeout 등의 비동기 작업 내 여러 상태 업데이트를 단일 리렌더링으로 묶어 효율성을 극대화합니다 [31-34]. 최근 도입된 React Compiler는 빌드 단계에서 구문 트리를 분석하여 수동 처리 없이 자동으로 메모이제이션을 삽입해 개발자의 성능 최적화 부담을 줄여줍니다 [35-38].
* **CSR vs SSR vs SSG 전략적 렌더링:**
* **CSR (Client-Side Rendering):** 브라우저가 빈 HTML과 JavaScript를 다운로드해 UI를 구성하며, 초기 로딩과 SEO에는 불리하지만 이후 빠르고 매끄러운 상호작용을 제공하여 단일 페이지 애플리케이션(SPA)에 적합합니다 [39-42].
* **SSR (Server-Side Rendering):** 서버에서 완전한 HTML을 미리 생성하여 브라우저에 전달하므로 초기 콘텐츠 렌더링(FCP)이 빠르고 SEO에 매우 유리합니다 [43-46].
* **SSG (Static Site Generation):** 빌드 시점에 모든 HTML을 미리 렌더링하여 CDN을 통해 즉시 제공하므로 가장 빠르지만, 실시간 데이터 반영이 어렵습니다 [47-50].
* **React Server Components (RSC):** 오직 서버에서만 실행되어 클라이언트에 JavaScript 번들을 전혀 전송하지 않는 컴포넌트 구조로, 클라이언트 번들 크기를 대폭 줄이고 서버 리소스에 직접 접근할 수 있습니다 [51-54].
* **컴포넌트 기반 아키텍처 (CBA):** React의 핵심 설계 원칙으로, 애플리케이션을 독립적이고 캡슐화된 재사용 가능한 컴포넌트 단위로 나눕니다 [55-58]. 이는 시스템의 복잡성을 낮추고, 병렬 개발을 가능하게 하며, 특정 컴포넌트의 렌더링 주기만을 독립적으로 관리 및 최적화할 수 있도록 지원합니다 [59-64].
## 🔗 Knowledge Connections
- **Related Topics:** [[Critical Rendering Path]], [[Virtual DOM]], [[React Fiber Architecture]], [[React Compiler]], [[Hydration]]
- **Projects/Contexts:** [[SPA (Single Page Application)]], [[Next.js]]
- **Contradictions/Notes:** SSR은 검색 엔진 최적화(SEO) 및 빠른 초기 콘텐츠 렌더링(FCP) 측면에서 유리하지만 [43, 65], 사용자가 시각적으로 완성된 페이지를 보더라도 클라이언트가 JavaScript 번들을 다운로드하고 실행하는 Hydration(수화) 과정이 완료되기 전까지는 상호작용이 불가능하므로, TTI(Time to Interactive) 지표에서는 CSR보다 수치가 낮게 나타나는 렌더링 병목 현상이 존재합니다 [66-69].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[React Server Components (RSC)]]
## 📌 Brief Summary
React Server Components(RSC)는 컴포넌트가 오직 서버에서만 실행되고 클라이언트로 JavaScript 번들을 전혀 전송하지 않는 혁신적인 렌더링 아키텍처입니다 [1-3]. 기존의 SSR(Server-Side Rendering)과 달리 상호작용이 필요 없는 정적 컴포넌트의 Hydration(수화) 과정을 생략하며, 직렬화된 UI 표현만을 브라우저로 스트리밍합니다 [2, 4, 5]. 결과적으로 클라이언트의 JavaScript 처리 부하를 대폭 줄이고, 초기 로딩 속도와 상호작용 성능 지표인 INP(Interaction to Next Paint)를 향상시키는 렌더링 최적화의 핵심 기술입니다 [1, 2].
## 📖 Core Content
* **아키텍처와 작동 원리 (Architecture & Mechanics)**
RSC는 브라우저가 아닌 서버 환경에서 완전히 실행되므로 데이터베이스, 로컬 파일 시스템, 비공개 환경 변수에 직접 접근할 수 있습니다 [6, 7]. 렌더링 결과물은 단순한 HTML뿐만 아니라, 클라이언트가 UI를 조립하는 데 사용하는 직렬화된 React 지시어(React Flight 프로토콜)와 함께 브라우저에 전달됩니다 [5]. 브라우저는 이 결과물을 받아 즉시 화면에 렌더링하며, 이 과정에서 해당 서버 컴포넌트의 JavaScript 코드는 0바이트로 클라이언트에 전송되지 않습니다 [1, 3, 6].
* **SSR과의 본질적 차이점 및 Hydration 제거**
전통적인 SSR은 서버에서 HTML을 미리 생성해 초기 콘텐츠 표시 속도(FCP)를 높이지만, 브라우저가 페이지를 대화형으로 만들기 위해 여전히 전체 JavaScript 번들을 다운로드하고 'Hydration' 과정을 거쳐야만 합니다 [8, 9]. 반면 순수한 RSC는 브라우저에서 실행될 JS 코드가 애초에 존재하지 않으므로 Hydration 단계 자체가 생략되며 클라이언트 메인 스레드의 연산 부담을 극적으로 줄여줍니다 [2, 4, 7].
* **Client Components와의 하이브리드 아키텍처**
상태(State) 관리나 이벤트 핸들러(onClick 등), 브라우저 API 접근이 필요한 대화형 요소는 파일 최상단에 `"use client"` 지시어를 선언하여 클라이언트 컴포넌트로 분리합니다 [6, 10, 11]. 서버 컴포넌트는 클라이언트 컴포넌트를 렌더링할 수 있지만, 클라이언트 컴포넌트는 서버 컴포넌트를 직접 임포트할 수 없다는 엄격한 단방향 의존성 규칙(서버 → 클라이언트)을 따릅니다 [12-14]. 이를 통해 무거운 비상호작용 UI는 서버에 남겨두고 상호작용에 필수적인 부분만 브라우저로 전송하여 번들 크기를 최적화할 수 있습니다 [6, 13].
* **데이터 페칭(Data Fetching)의 최적화**
RSC 환경에서는 컴포넌트 내부에서 별도의 API 중간 계층 없이 데이터베이스에 직접 비동기 요청(async/await)을 수행할 수 있습니다 [15, 16]. 또한 서버 환경의 이점을 살려 렌더링 중 데이터를 병렬로 가져옴으로써, 전통적인 클라이언트 렌더링(CSR)에서 발생하던 데이터 페칭 워터폴(Waterfall) 문제를 효과적으로 제거할 수 있습니다 [17, 18].
* **제약 사항 및 구현 시 주의점 (Pitfalls)**
서버 컴포넌트는 브라우저 API나 상태(State)를 가질 수 없으므로 대화형 인터랙션을 구현할 수 없습니다 [19]. 또한 렌더링 및 데이터 구조를 잘못 설계하여 서버 내에서 순차적으로 데이터를 페칭하게 되면, 기존 클라이언트의 워터폴 문제가 '서버 측 워터폴(Server-Side Waterfalls)'로 그대로 전이되어 응답 지연을 유발할 수 있습니다 [20, 21]. 구조적 문제를 우회하기 위해 `"use client"`를 무분별하게 남용하면 대규모 JS 번들이 다시 클라이언트로 전송되어 RSC 도입의 최적화 이점이 완전히 사라지게 됩니다 [22].
## 🔗 Knowledge Connections
- **Related Topics:** [[Server-Side Rendering (SSR)]], [[Client-Side Rendering (CSR)]], [[Hydration]], [[Component-Based Architecture (CBA)]], [[Interaction to Next Paint (INP)]]
- **Projects/Contexts:** [[Next.js App Router]], [[React 19]], [[React Flight Protocol]]
- **Contradictions/Notes:** 소스는 RSC가 단순히 "향상된 SSR"이 아니라고 명확히 선을 긋습니다. SSR은 여전히 클라이언트에 자바스크립트를 전송하고 하이드레이션을 수행해야 하지만, RSC는 특정 컴포넌트의 클라이언트 측 자바스크립트와 하이드레이션 자체를 완전히 제거한다는 점에서 본질적인 차이가 있습니다 [7, 9]. 또한 서버 컴포넌트를 도입한다고 자동으로 성능이 최적화되는 것은 아니며, 데이터 의존성을 직렬로 잘못 구성하면 서버 상에서 동일한 워터폴 현상(Server-Side Waterfalls)을 일으켜 병목을 초래할 수 있다고 경고합니다 [20, 21, 23].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[React 성능 최적화]]
## 📌 Brief Summary
React 성능 최적화는 불필요한 리렌더링을 방지하고 번들 크기를 줄여 애플리케이션의 로딩 속도와 상호작용 반응성을 향상시키는 일련의 과정입니다 [1, 2]. 주요 원인인 리렌더링 캐스케이드와 큰 초기 자바스크립트 번들을 해결하기 위해 메모이제이션, 코드 분할, 가상화 등의 기술이 활용됩니다 [1-5]. 최근에는 React 18의 자동 배칭(Automatic Batching)과 동시성(Concurrent) 기능, React 19의 자동 메모이제이션을 지원하는 React Compiler가 도입되어 성능 최적화 작업이 더욱 자동화되고 효율적으로 발전하고 있습니다 [6-9].
## 📖 Core Content
* **성능 저하의 주요 원인**: 부모 컴포넌트의 상태 변경 시 속성(props) 변경 여부와 관계없이 모든 자식 컴포넌트가 다시 렌더링되는 '리렌더링 캐스케이드(Re-Render Cascade)'가 가장 일반적인 원인입니다 [1]. 또한 대규모 자바스크립트 번들로 인한 초기 로드 지연, 렌더링 시마다 실행되는 무거운 데이터 연산, 인라인 객체 및 함수 생성 등도 성능을 저하시킵니다 [2, 10, 11].
* **주요 성능 최적화 기법**:
* **코드 분할 (Code Splitting)**: `React.lazy()`와 Suspense를 라우트 수준에서 활용하면 애플리케이션을 작은 청크로 나누어 로드할 수 있어 초기 번들 크기를 30~50%까지 줄이고 LCP(최대 콘텐츠풀 페인트)를 개선할 수 있습니다 [3].
* **메모이제이션 (Memoization)**: `React.memo`, `useMemo`, `useCallback`을 사용하여 변경되지 않은 속성에 대한 불필요한 리렌더링을 방지합니다 [4, 12].
* **리스트 가상화 (Virtualization)**: 화면에 수천 개의 항목이 있는 리스트를 렌더링할 때, 뷰포트에 보이는 항목과 약간의 버퍼만 실제 DOM 노드로 렌더링하여 DOM 크기와 렌더링 시간을 대폭 단축합니다 [5, 13].
* **DOM 구조 최적화**: React Fragment(`<></>`)를 사용하여 구조를 위한 불필요한 래퍼(wrapper) DOM 노드 추가를 방지하고 누적 레이아웃 이동(CLS) 지표를 향상시킵니다 [14, 15].
* **렌더링 전략 활용 (SSR, SSG, RSC)**: 서버 사이드 렌더링(SSR)이나 정적 사이트 생성(SSG)을 도입해 자바스크립트 실행 전 초기 화면 표시 속도를 높입니다 [10, 16, 17]. 특히 React Server Components(RSC)는 클라이언트 번들에 자바스크립트를 전혀 포함하지 않고 서버에서 독점적으로 실행되어 상호작용 속도를 크게 높입니다 [18-20].
* **React 버전별 최적화 기능의 진화**:
* **React 18**: 여러 상태 업데이트를 하나로 묶어 리렌더링을 최소화하는 '자동 배칭(Automatic Batching)'이 네이티브 이벤트뿐만 아니라 비동기 작업에도 기본 적용되었습니다 [7, 21, 22]. 또한, `useTransition``useDeferredValue` 훅을 통해 무거운 연산이 메인 스레드를 차단하지 않고 렌더링을 지연시킬 수 있는 동시성(Concurrent) 기능이 도입되었습니다 [6, 23, 24].
* **React 19 (React Compiler)**: 개발자가 수동으로 작성하던 메모이제이션을 빌드 타임에 AST(추상 구문 트리)를 분석하여 자동으로 처리해 주는 컴파일러가 도입되었습니다 [8, 9, 25]. 이를 통해 개발자는 코드의 유지보수성을 높이면서도 세밀한 반응성(fine-grained reactivity)을 확보할 수 있습니다 [8, 26].
* **측정 기반의 최적화**: 직관에 의존하는 대신 React DevTools Profiler, Lighthouse 등 측정 도구를 활용하여 실제 렌더링 병목 지점과 Core Web Vitals 지표를 먼저 파악한 후 최적화를 진행해야 합니다 [27-31].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Core Web Vitals]], [[React Compiler]], [[React Server Components]], [[Automatic Batching]]
- **Projects/Contexts:** [[Next.js]], [[Meta Quest Store]] (React Compiler를 제품에 적용하여 초기 로드 12% 및 상호작용 속도 2.5배 개선 [32]), [[Sanity Studio]] (React Compiler 적용으로 렌더링 시간 20-30% 단축 [33])
- **Contradictions/Notes:** 여러 소스에 따르면 메모이제이션(`useMemo`, `useCallback`, `React.memo`)은 리렌더링 방지에 강력한 도구이지만, 프로파일링 측정 없이 모든 컴포넌트에 무분별하게 적용할 경우 오히려 연산 오버헤드와 메모리 사용량을 가중시켜 애플리케이션의 성능을 저하시키는 원인(안티 패턴)이 될 수 있다고 공통적으로 경고합니다 [12, 34].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,19 @@
# [[React가 빠른 이유]]
## 📌 Brief Summary
React는 실제 DOM을 직접 조작할 때 발생하는 비용(Reflow 및 Repaint)을 최소화하기 위해 가상 DOM(Virtual DOM)과 효율적인 재조정(Reconciliation) 알고리즘을 사용합니다 [1]. 또한 Fiber 아키텍처를 도입하여 렌더링 작업을 잘게 쪼개고 우선순위에 따라 동시성(Concurrent) 렌더링을 처리함으로써 UI의 반응성을 극대화합니다 [2-4]. 최근 버전에서는 자동 배칭(Automatic Batching)과 React Compiler의 자동 메모이제이션을 통해 불필요한 재렌더링을 획기적으로 줄여 더욱 빠르고 최적화된 성능을 제공합니다 [5-8].
## 📖 Core Content
* **가상 DOM(Virtual DOM)과 재조정(Reconciliation):** 실제 DOM을 직접 수정하는 작업은 브라우저 렌더링 경로(CRP)에서 레이아웃(Reflow)과 페인트(Repaint) 과정을 유발하여 본질적으로 느립니다 [1]. React는 메모리 내에 가벼운 UI 표현인 가상 DOM을 유지합니다 [1, 9, 10]. UI 상태가 변경되면 새로운 가상 DOM을 생성하고 이전 상태와 비교(Diffing)한 뒤, 실제 DOM을 최소한으로만 업데이트(Patch)하는 재조정 과정을 거쳐 불필요한 연산을 방지합니다 [1, 9, 10].
* **O(n) 휴리스틱 Diffing 알고리즘:** 두 트리를 비교하는 일반적인 알고리즘은 $O(n^3)$의 복잡도를 가지므로 실시간 애플리케이션에 부적합합니다 [11, 12]. React는 서로 다른 타입의 요소는 전혀 다른 트리를 생성한다고 가정하고, 개발자가 제공하는 'Key'를 통해 요소를 식별하는 방식을 사용하여 복잡도를 $O(n)$으로 낮춘 휴리스틱 알고리즘을 사용합니다 [11, 12]. 이를 통해 기존 DOM 노드를 최대한 보존하며 속도를 높입니다 [2, 13].
* **Fiber 아키텍처와 동시성(Concurrent) 렌더링:** 과거 React의 스택 재조정자(Stack Reconciler)는 동기적으로 전체 트리를 처리하여 메인 스레드를 차단하는 문제가 있었습니다 [3]. React 16부터 도입된 Fiber 아키텍처는 렌더링 작업을 '작업 단위(Unit of work)'로 분할합니다 [3, 14]. 우선순위 차선(Lane) 모델과 타임 슬라이싱(Time-slicing)을 사용하여 높은 우선순위의 작업(예: 사용자 입력)이 들어오면 기존의 렌더링을 일시 중지하고 양보(Yield)한 뒤 나중에 재개할 수 있도록 해 UI 차단을 방지합니다 [3, 4, 15, 16].
* **자동 배칭(Automatic Batching):** React 18은 브라우저 이벤트뿐만 아니라 Promise나 setTimeout과 같은 비동기 작업 내에서 발생하는 여러 상태 업데이트를 단일 재렌더링으로 묶어 처리합니다 [5, 17, 18]. 결과적으로 가상 DOM Diffing 과정과 CPU 작업이 줄어들어 렌더링 횟수가 급감하고 프레임 속도가 향상됩니다 [5, 7, 19, 20].
* **React Compiler에 의한 자동 메모이제이션:** React 19에 도입된 컴파일러는 빌드 시점에 추상 구문 트리(AST)를 분석하여 컴포넌트와 훅 내의 계산 비용이 높은 작업에 자동으로 메모이제이션 경계를 삽입합니다 [6, 21-23]. 이는 개발자의 수동 메모이제이션(useMemo, useCallback 등) 부담을 없애고, 입력값이 변경될 때만 세밀하게 재렌더링을 유도하여 폭포수 같은 연쇄 재렌더링 성능 저하를 방지합니다 [6, 8, 23, 24].
## 🔗 Knowledge Connections
- **Related Topics:** `[[Virtual DOM]]`, `[[Reconciliation]]`, `[[Fiber Architecture]]`, `[[Automatic Batching]]`, `[[React Compiler]]`, `[[Reflow & Repaint]]`
- **Projects/Contexts:** `[[프론트엔드 렌더링 최적화(Rendering Optimization)]]`, `[[브라우저 렌더링 파이프라인(Critical Rendering Path)]]`
- **Contradictions/Notes:** 상태 트리를 비교할 때 발생하는 기존 알고리즘의 O(n³) 복잡도 한계를 O(n)으로 해결한 것이 속도의 주요 기반입니다 [11, 12]. 또한, Fiber 아키텍처에서 렌더링(Render) 단계는 중단하고 재개할 수 있는 순수 계산 과정이지만, 커밋(Commit) 단계는 DOM을 실제로 조작해야 하므로 동기식으로 차단되어 실행된다는 점이 아키텍처의 핵심적인 구분입니다 [25-27].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,29 @@
# [[Reconciliation]]
## 📌 Brief Summary
Reconciliation(재조정)은 React가 메모리에 유지되는 가상 DOM(Virtual DOM)과 브라우저의 실제 DOM을 동기화하여 UI를 가장 효율적으로 업데이트하는 과정입니다 [1, 2]. React는 요소의 타입과 `key` 속성에 기반한 $O(n)$ 복잡도의 휴리스틱 Diffing(비교) 알고리즘을 사용하여 전통적인 트리 비교 알고리즘의 비효율성을 극복합니다 [1, 3]. 이를 통해 DOM에 대한 불필요한 수정과 브라우저의 리플로우(Reflow)/리페인트(Repaint)를 최소화하며, "React가 빠른 이유"를 설명하는 핵심적인 메커니즘입니다 [3, 4].
## 📖 Core Content
* **가상 DOM(Virtual DOM)과 재조정의 필요성**:
브라우저의 DOM을 직접 수정하는 작업은 Critical Rendering Path 상의 레이아웃(Reflow)과 페인트 단계를 트리거하므로 본질적으로 성능 비용이 높습니다 [4, 5]. React는 개발자가 선언적으로 UI 상태를 묘사하면 내부적으로 가벼운 가상 DOM 트리를 구축하고, 상태나 props 변경 시 이전 트리와 새로운 트리를 비교(Diff)하여 변경된 최소한의 부분만 실제 DOM에 반영(Patch)합니다 [2, 4, 5].
* **휴리스틱 Diffing 알고리즘 ($O(n)$ 최적화)**:
두 트리를 완벽하게 비교하는 일반적인 알고리즘은 $O(n^3)$의 시간 복잡도를 가져 대규모 렌더링에 사용할 수 없습니다(1,000개 요소 비교 시 약 10억 번의 연산 필요) [1, 3]. 따라서 React는 다음 두 가지 강력한 가정을 통해 이를 $O(n)$으로 최적화했습니다 [3, 6]:
1. **서로 다른 타입의 엘리먼트는 완전히 다른 트리를 생성한다**: 루트 엘리먼트의 태그나 컴포넌트 타입이 변경될 경우(예: `<a>``<img>` 또는 `<Article>``<Comment>`), React는 기존 트리를 완전히 파괴(Unmount)하고 새로운 DOM 노드를 처음부터 구축합니다 [6, 7].
2. **`key` prop을 통한 자식 요소 안정성 보장**: 리스트의 순서가 바뀌거나 맨 앞에 새 엘리먼트가 추가될 때, 자식을 순차적으로 비교하면 모든 요소를 변경하는 비효율이 발생합니다 [8, 9]. 대신 고유한 `key`를 제공하면 원래 트리의 자식과 새로운 트리의 자식을 매칭하여, 불필요한 재생성 없이 요소들의 위치만 효율적으로 이동시킵니다 [6, 9, 10].
* **동일한 타입의 엘리먼트 및 컴포넌트 처리**:
동일한 DOM 태그를 비교할 때는 기본 DOM 노드를 유지하고 `className`이나 `style` 등 변경된 속성 정보만 부분적으로 업데이트합니다 [11, 12]. 사용자 정의 컴포넌트 역시 타입이 같다면 컴포넌트 인스턴스와 상태(State)가 유지되며, 변경된 props만 전달받은 뒤 `render()` 함수를 재실행하여 하위 트리에 대해 재조정을 반복 수행합니다 [8, 12].
* **Fiber 아키텍처를 통한 스케줄링 및 동시성 렌더링**:
과거 React의 재조정은 트리 전체를 한 번에 동기식으로 처리(Stack Reconciler)하여 메인 스레드를 장시간 차단하는 문제가 있었습니다 [13]. React 16부터는 이 엔진을 **Fiber 아키텍처**로 재작성하여 렌더링 작업을 작고 중단 가능한 단위(Fiber nodes)로 나누었습니다 [13-15].
재조정 과정은 순수하고 중단 및 재시작이 가능한 **렌더 단계(Render Phase)**와 계산된 DOM 변경 사항(Effect list)을 동기적으로 한 번에 적용하는 **커밋 단계(Commit Phase)**로 분리됩니다 [16-18]. 이를 통해 우선순위(Lanes)에 따라 사용자 입력 같은 긴급한 업데이트가 무거운 렌더링 작업을 중단하고 먼저 처리될 수 있습니다 [19-21].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Fiber Architecture]], [[Diffing Algorithm]], [[Reflow / Repaint]]
- **Projects/Contexts:** [[React 성능 최적화]] (불필요한 DOM 노드 재생성을 막아 브라우저 렌더링 파이프라인의 오버헤드를 줄이는 프론트엔드 최적화 단계)
- **Contradictions/Notes:** React의 재조정 알고리즘은 휴리스틱에 의존하므로, `key`에 배열의 인덱스를 사용하거나 `Math.random()`처럼 매번 변경되는 불안정한 값을 사용하면 안 됩니다. 이 경우 요소의 순서가 변경될 때 내부 상태가 엉키거나 불필요한 DOM 노드가 대량으로 다시 생성되어 성능 저하를 초래합니다 [22, 23].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,28 @@
# [[Reflow / Repaint 최소화 방법]]
## 📌 Brief Summary
Reflow(Layout)와 Repaint(Paint)는 브라우저 렌더링 과정에서 요소의 크기, 위치를 계산하고 시각적 요소를 화면에 그리는 비용이 높은 작업입니다. 브라우저의 렌더링 최적화를 달성하고 매끄러운 사용자 경험(예: 60fps 유지)을 제공하기 위해서는 DOM 트리의 깊이 감소, 상태 변경의 일괄 처리, 하드웨어 가속 등을 통해 이 과정이 발생하는 빈도와 연산량을 최소화해야 합니다.
## 📖 Core Content
**DOM 구조 및 CSS 규칙 최적화**
* 불필요한 DOM 트리의 깊이를 줄여야 합니다. DOM 트리의 특정 노드가 변경되면 루트부터 하위 노드까지 계산이 파급되어 Reflow에 소요되는 시간이 길어집니다 [1]. React의 경우, 불필요한 래퍼(wrapper) 대신 Fragment를 사용하여 DOM 노드 수를 줄이면 브라우저의 레이아웃과 페인트 속도를 개선할 수 있습니다 [2, 3].
* 사용하지 않는 CSS 규칙을 최소화하고, 특히 하위 선택자(descendant selectors)와 같이 CPU 연산력을 더 많이 요구하는 복잡한 CSS 선택자의 사용을 피하는 것이 좋습니다 [1]. `display: none`을 사용하면 요소가 Render Tree에서 완전히 제거되어 레이아웃에서 배제되므로, 렌더링을 억제할 때 유용하게 활용할 수 있습니다 [4].
**DOM 접근 및 수정의 일괄 처리 (Batching)**
* 요소의 크기나 위치 등을 계산하는 속성을 반복적으로 읽고 쓰는 작업을 교차로 실행하면 "레이아웃 스래싱(Layout Thrashing)"이라는 비효율적인 Reflow가 발생합니다 [5].
* 이를 방지하기 위해서는 DOM 값을 읽는 단계와 수정하는 단계를 명확히 분리하여 렌더링 엔진의 작업을 일괄 처리(batch)해야 합니다 [6, 7].
* 루프 내부에서 DOM을 조작하는 것을 피하고, 접근해야 하는 DOM 노드나 속성값을 변수에 캐싱(Caching)하여 불필요하게 DOM 구조에 반복적으로 접근하는 것을 최소화해야 합니다 [6, 8].
**애니메이션 최적화 및 하드웨어 가속(GPU) 활용**
* 박스 모델의 속성(`width`, `height`, `margin`, `top`, `left` 등)을 직접적으로 애니메이션 처리하는 것은 피해야 합니다 [9, 10].
* 대신 시각적 변화나 애니메이션 처리를 할 때 CSS의 `transform` 속성(예: `transform: translate()`)이나 `opacity`를 사용하면 브라우저가 새로운 Reflow나 Repaint 주기를 유발하지 않고 GPU를 통해 해당 요소를 자체 레이어에서 처리할 수 있습니다 [11-14].
* 복잡한 렌더링 변경이나 애니메이션을 수행할 때는 `position: absolute` 또는 `position: fixed`를 적용하여 해당 요소를 문서의 일반적인 흐름(flow)에서 분리시켜 다른 요소에 미치는 Reflow 영향을 최소화해야 합니다 [1].
* JavaScript로 애니메이션을 동기화해야 하는 경우 `window.requestAnimationFrame`을 사용하여 브라우저가 동시 애니메이션을 단일 Reflow 및 Repaint 주기로 통합 최적화할 수 있도록 지원해야 합니다 [13, 15].
## 🔗 Knowledge Connections
- **Related Topics:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[Virtual DOM]], [[렌더링 최적화 개념 설명 자료]]
- **Projects/Contexts:** [[React 기반 프론트엔드 성능 최적화]], [[단일 페이지 애플리케이션(SPA) UI 성능 관리]]
- **Contradictions/Notes:** 복잡한 CSS 선택자를 피하는 것은 성능 향상에 도움이 되지만, 소스에 따르면 매우 구체적인 CSS 규칙 최적화로 얻는 렌더링 속도 개선은 마이크로초 단위로 미미한 경우가 많습니다 [16]. 따라서 개발자는 직관적인 CSS 최적화에 매몰되기보다는 반드시 측정 도구를 통해 가장 느린 병목 현상(Reflow/Repaint가 잦은 곳)을 찾아 우선순위를 두고 최적화해야 합니다 [16, 17].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,34 @@
# [[Reflow / Repaint]]
## 📌 Brief Summary
**Reflow(레이아웃)**는 브라우저가 화면에 표시될 DOM 요소들의 정확한 위치와 기하학적 크기를 재계산하는 과정이며, **Repaint(페인트)**는 레이아웃의 변화 없이 요소의 색상이나 그림자 같은 시각적 속성만을 화면에 다시 그리는 과정입니다 [1-6]. 이 두 과정은 웹 페이지 렌더링에 필수적이지만 연산 비용이 높아 과도하게 발생할 경우 애플리케이션의 성능 저하와 버벅거림(Jank)을 유발하므로 프론트엔드 최적화의 핵심 대상이 됩니다 [7-9].
## 📖 Core Content
* **Reflow (Layout) 개념 및 발생 원인**
* Reflow는 문서 흐름 내에서 요소의 위치, 크기(width, height, margin, padding, border 등)를 계산하는 과정입니다 [1, 4, 6].
* DOM 요소의 추가 및 제거, 브라우저 창 크기 조절, 폰트 크기 변경, 또는 레이아웃에 영향을 주는 CSS 속성 변경 시 트리거됩니다 [4-6, 10].
* 웹 문서는 연속적인 흐름으로 구성되어 있어, 단일 요소의 구조적 변화가 부모나 자식 요소 등 DOM 트리 전체에 걸친 재계산을 연쇄적으로 유발할 수 있으므로 연산 비용이 매우 높은 사용자 차단(User-blocking) 작업입니다 [1, 3, 5, 6].
* **Repaint (Paint) 개념 및 발생 원인**
* Repaint는 레이아웃에 영향을 주지 않고, 요소의 가시성, 배경색, 텍스트 색상, 그림자 등의 시각적 스타일만 변경될 때 발생합니다 [2, 4, 6].
* 기하학적 재계산이 필요하지 않아 Reflow보다는 상대적으로 비용이 적지만, 애니메이션 처리 중 불필요하게 자주 발생하면 여전히 프레임 드랍이나 성능 저하를 초래할 수 있습니다 [7, 9, 11].
* **Reflow / Repaint 최소화 및 렌더링 최적화 방법**
* **DOM 조작 일괄 처리(Batching) 및 레이아웃 스래싱(Layout Thrashing) 방지**: DOM 읽기 및 쓰기 작업을 혼합하지 않고 한 번에 처리하여 브라우저가 레이아웃을 여러 번 재계산하는 것을 방지해야 합니다 [2, 8, 9, 12, 13].
* **GPU 가속 활용 (Compositing)**: `top`, `left`와 같은 레이아웃 속성 대신 `transform`을, 색상 변경 대신 `opacity`를 사용하여 애니메이션을 구현하면 Reflow나 Repaint 없이 브라우저가 별도 레이어에서 요소를 처리할 수 있습니다 [8, 9, 11].
* **구조 및 스타일 최적화**: DOM 트리의 깊이를 줄이고, 연산이 많이 필요한 복잡한 CSS 선택자(특히 자손 선택자)의 사용을 지양해야 합니다 [14]. 레이아웃 변화 없이 요소를 숨기려면 `display: none` (Reflow 유발) 대신 `visibility: hidden`을 사용하는 것이 좋습니다 [15].
* **문서 흐름(Flow)에서 분리**: 애니메이션 등 복잡한 렌더링 변경이 일어나는 요소는 `position: absolute` 또는 `position: fixed`를 사용하여 주변 요소의 Reflow에 영향을 주지 않도록 격리해야 합니다 [14].
* **React의 렌더링 메커니즘과 성능 최적화**
* 기존의 직접적인 DOM 조작은 매 변경마다 비용이 높은 Reflow와 Repaint를 유발하기 때문에 느릴 수밖에 없습니다 [16].
* React는 **Virtual DOM**을 사용하여 메모리 상에서 이전 상태와 새로운 상태를 비교(Diffing)한 뒤, 변경된 최소한의 부분만 실제 DOM에 일괄 반영함으로써 렌더링 파이프라인의 낭비를 방지합니다 [16, 17].
* 또한 React 18부터 도입된 **자동 일괄 처리(Automatic Batching)** 기능은 비동기 작업(Promise, setTimeout 등) 내에서 발생하는 여러 상태 업데이트를 단 한 번의 리렌더링으로 묶어서 처리하여 DOM 연산 횟수를 획기적으로 줄여줍니다 [18-20].
## 🔗 Knowledge Connections
- **Related Topics:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[DOM vs Virtual DOM]]
- **Projects/Contexts:** [[React 기반 싱글 페이지 애플리케이션(SPA)의 렌더링 최적화]], [[Automatic Batching을 통한 React 18 성능 최적화]]
- **Contradictions/Notes:** 소스 문서들에 따르면 `display: none`은 요소를 렌더 트리에서 완전히 제거하므로 전체적인 레이아웃 계산(Reflow)을 유발하지만, 시각적으로만 보이지 않게 처리하는 `visibility: hidden`을 사용하면 Reflow를 피할 수 있다고 권장하고 있습니다 [15, 21].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,22 @@
# [[Server-Side Rendering (SSR)]]
## 📌 Brief Summary
Server-Side Rendering (SSR)은 사용자의 요청이 있을 때마다 서버 측에서 웹 페이지의 전체 HTML을 렌더링하여 클라이언트 브라우저로 전송하는 웹 렌더링 방식입니다 [1-3]. 브라우저는 완성된 HTML을 받아 즉시 화면에 표시하며, 이후 JavaScript를 다운로드하여 페이지를 상호작용 가능하게 만드는 하이드레이션(Hydration) 과정을 거치게 됩니다 [1, 4-6]. 이 방식은 검색 엔진 최적화(SEO)와 초기 화면 표시에 매우 유리하지만, 서버 부하 증가와 상호작용 지연(TTI)이라는 성능적 트레이드오프를 동반합니다 [1, 7-9].
## 📖 Core Content
* **작동 원리와 하이드레이션 (Hydration):**
SSR 환경에서 사용자가 페이지를 요청하면, 서버는 라우팅 로직을 처리하고 데이터베이스나 API로부터 데이터를 가져와 완성된 HTML 문서를 생성하여 응답합니다 [2, 6]. 브라우저는 이 HTML을 즉시 화면에 렌더링하므로 사용자는 콘텐츠를 바로 볼 수 있지만, 이 시점의 페이지는 상호작용할 수 없는 정적인 상태입니다 [6]. 이후 브라우저가 JavaScript 번들을 다운로드하고 실행하면, React와 같은 프레임워크가 가상 DOM(Virtual DOM)을 렌더링된 HTML 구조에 매핑하여 이벤트 리스너를 연결하고 상태를 동기화합니다. 이 과정을 '하이드레이션'이라고 부릅니다 [1, 5, 10].
* **성능 및 사용자 경험적 이점:**
SSR의 가장 큰 장점 중 하나는 탁월한 검색 엔진 최적화(SEO)입니다. 검색 엔진 크롤러가 JavaScript 실행을 기다리거나 빈 화면을 볼 필요 없이 완전히 렌더링된 HTML 콘텐츠에 즉시 접근하여 색인을 생성할 수 있기 때문입니다 [1, 11, 12]. 또한 첫 콘텐츠 풀 페인트(FCP) 성능이 우수하여 사용자가 빈 화면 대신 즉각적으로 시각적 요소를 볼 수 있으며, 이는 대역폭이 제한된 모바일이나 느린 3G 네트워크 환경에서 사용자 경험을 크게 개선합니다 [9, 11, 12]. 매 요청마다 서버에서 렌더링이 이루어지므로, 뉴스 사이트나 전자상거래의 제품 페이지처럼 항상 최신의 동적 데이터를 제공해야 하는 환경에 이상적입니다 [13-15].
* **인프라 한계 및 성능 트레이드오프:**
모든 사용자 상호작용이나 페이지 요청 시 서버가 렌더링 연산을 수행해야 하므로 트래픽 급증 시 서버 컴퓨팅 부하가 급격히 커지며, 이는 호스팅 인프라 비용 증가와 복잡성 확대로 이어집니다 [7, 8, 16]. 서버 측에서의 HTML 생성 작업으로 인해 첫 바이트 도달 시간(TTFB)이 약 100~300ms가량 늘어날 수 있습니다 [9, 17]. 무엇보다 사용자가 가장 불편함을 느낄 수 있는 단점은 '상호작용 지연'입니다. 화면의 시각적 요소는 빠르게 로드되지만, JavaScript가 다운로드되고 하이드레이션이 완료될 때까지(기기에 따라 2~5초가량 소요될 수 있음) 페이지가 클릭이나 입력 등의 상호작용에 반응하지 않는 상호작용 시간(TTI) 저하 현상이 발생합니다 [1, 9, 10, 16].
## 🔗 Knowledge Connections
- **Related Topics:** [[Client-Side Rendering (CSR)]], [[Static Site Generation (SSG)]], [[Hydration]], [[Virtual DOM]], [[Search Engine Optimization (SEO)]], [[First Contentful Paint (FCP)]], [[Time to Interactive (TTI)]]
- **Projects/Contexts:** [[Next.js]], [[React Server Components (RSC)]], [[E-commerce Platforms]]
- **Contradictions/Notes:** 소스 문헌들은 공통적으로 SSR이 시각적 로드(FCP)를 빠르게 만들어 사용자에게 즉각적인 응답을 제공하지만, 하이드레이션 병목 현상으로 인해 실질적인 상호작용(TTI)은 CSR보다 지연된다는 성능적 역설을 주의해야 한다고 지적합니다 [9, 18].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,18 @@
# [[Time to Interactive (TTI)]]
## 📌 Brief Summary
Time to Interactive (TTI)는 사용자의 초기 페이지 요청(DNS 조회 및 TCP 연결) 시점부터 웹 페이지가 50ms 이내에 사용자의 상호작용에 응답할 수 있는 상태가 되기까지 걸리는 시간을 측정하는 성능 지표입니다 [1]. 시각적인 콘텐츠가 화면에 표시되는 것을 넘어, 필요한 JavaScript가 모두 다운로드되고 실행되어 버튼 클릭 등의 입력에 즉각적으로 반응할 수 있는 시점을 의미합니다 [1, 2]. 특히 서버 사이드 렌더링(SSR) 환경에서는 화면이 먼저 보이지만 JavaScript가 연결(Hydration)될 때까지 상호작용이 불가능한 지연 현상이 발생하므로 TTI 최적화가 매우 중요합니다 [2, 3].
## 📖 Core Content
* **TTI의 정의와 메인 스레드의 역할:** TTI는 페이지의 First Contentful Paint (FCP) 이후, 사용자의 입력(스크롤, 터치 등)에 50ms 이내로 응답할 수 있게 되는 시점을 측정합니다 [1]. 브라우저의 메인 스레드가 JavaScript를 파싱, 컴파일, 실행하느라 점유되어 있다면, 페이지는 시각적으로 완성되었더라도 상호작용할 수 없는 상태가 됩니다 [1, 4].
* **SSR(Server-Side Rendering)과 Hydration에 따른 TTI 지연:** SSR은 서버에서 미리 렌더링된 HTML을 제공하므로 초기 콘텐츠 표시(FCP)가 빠르지만, TTI 측면에서는 불리할 수 있습니다 [2, 3, 5]. 화면의 요소가 클릭 가능해 보이더라도, JavaScript 번들이 다운로드되고 정적 HTML에 이벤트 리스너와 상태를 연결하는 'Hydration' 과정이 완료될 때까지는 반응하지 않기 때문입니다 [2, 3, 6]. JavaScript 번들 크기가 크거나 기기 성능이 낮을 경우 이 과정에 2~5초가 소요될 수 있으며, 이는 사용자에게 답답한 경험을 제공할 수 있습니다 [2, 5-7].
* **CSR(Client-Side Rendering)과의 비교:** CSR의 경우, 초기에 브라우저가 빈 HTML 셸을 받고 JavaScript를 다운로드해야 하므로 초기 화면 표시는 느릴 수 있습니다 [8, 9]. 하지만 JavaScript 로드 후 클라이언트 측에서 렌더링이 완료되면 즉각적인 상호작용이 가능해지므로 초기 로드 이후의 TTI는 향상되는 특징을 가집니다 [10, 11].
* **성능 최적화 관점:** TTI를 개선하기 위해서는 메인 스레드의 점유 시간을 최소화해야 합니다 [4]. 이를 위해 점진적/선택적 Hydration 기법을 적용하여 중요한 상호작용 요소를 먼저 로드하거나 [12, 13], React Server Components(RSC)를 활용하여 브라우저로 전송되는 JavaScript 번들 크기 자체를 줄임으로써 Hydration에 소요되는 비용을 원천적으로 제거할 수 있습니다 [14, 15].
## 🔗 Knowledge Connections
- **Related Topics:** [[Hydration]], [[Server-Side Rendering (SSR)]], [[Client-Side Rendering (CSR)]], [[First Contentful Paint (FCP)]], [[메인 스레드 (Main Thread)]]
- **Projects/Contexts:** [[렌더링 최적화 개념 설명 자료]], [[React가 빠른 이유]]
- **Contradictions/Notes:** 소스에 따르면 SSR과 CSR은 뚜렷한 트레이드오프를 가집니다. SSR은 FCP(초기 콘텐츠 표시)가 빠르지만 Hydration 오버헤드로 인해 TTI가 느려지는 반면, CSR은 초기 로드 속도는 느리지만 로드 이후의 상호작용(TTI 향상)은 더 부드럽고 즉각적이라는 특징이 있습니다 [11, 16-18].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,26 @@
# [[Total Blocking Time (TBT)]]
## 📌 Brief Summary
Total Blocking Time(TBT)는 브라우저의 메인 스레드가 자바스크립트 실행 등으로 인해 차단되어 사용자 상호작용(입력, 클릭 등)을 처리할 수 없는 시간을 측정하는 핵심 성능 지표입니다 [1, 2]. 이 지표는 Lighthouse 성능 점수의 30%를 차지하며, 사용자 경험과 SEO 순위에 직접적인 영향을 미칩니다 [1]. 특히 React 환경에서는 서버 사이드 렌더링(SSR) 이후 전체 페이지를 한 번에 하이드레이션(Hydration)할 때 TBT가 급증하여 심각한 성능 저하와 입력 지연을 유발할 수 있습니다 [1, 3].
## 📖 Core Content
* **하이드레이션(Hydration)과 TBT의 상관관계**
* React는 기본적으로 사용자 화면에 즉시 보이지 않는 컴포넌트까지 포함하여 전체 페이지를 동시에 하이드레이션합니다 [1].
* 이러한 접근 방식은 불필요한 자바스크립트 실행을 유발하여 브라우저의 메인 스레드를 차단(Block)하게 되고, 결과적으로 긴 TBT와 Lighthouse 점수 하락으로 이어집니다 [1, 3].
* TBT가 길어지면 사용자가 페이지 로드 직후 버튼을 클릭해도 즉각적으로 반응하지 않는 심각한 입력 지연(Input lag)을 경험하게 됩니다 [1, 4].
* **중요 렌더링 경로(CRP)에서의 차단 시간**
* TBT는 하이드레이션뿐만 아니라 브라우저의 초기 렌더링 과정과도 관련이 있습니다.
* CSSOM을 구축하는 과정에서 CSS 선택자(Selector)의 복잡성은 렌더링 속도에 영향을 미치므로, 선택자의 명시성(specificity)을 최적화하고 CSS를 최소화(minify)하는 것은 중요 렌더링 경로(CRP)의 총 차단 시간을 줄이는 기본적인 최적화 기술입니다 [5].
* **TBT를 최소화하는 렌더링 최적화 전략**
* **선택적 하이드레이션 및 점진적 로딩 (Selective Hydration & Progressive Loading):** 모든 것을 한 번에 하이드레이션하는 대신, 스크롤 상단(above-the-fold) 콘텐츠를 우선 처리하고 덜 중요한 컴포넌트는 지연시킵니다 [6]. Next.js의 동적 가져오기(`next/dynamic`)를 활용하면 자바스크립트 실행을 분산시켜 메인 스레드 차단을 막고 TBT를 크게 줄일 수 있습니다 [6, 7].
* **가시성 기반 지연 하이드레이션 (Lazy Hydration Based on Visibility):** 화면 하단 콘텐츠가 뷰포트에 들어올 때만 하이드레이션되도록 지연시키는 방법(예: IntersectionObserver 활용)을 통해 특정 애플리케이션에서 TBT를 최대 40%까지 단축할 수 있습니다 [7, 8].
* **React 서버 컴포넌트 (React Server Components) 활용:** App Router와 같은 환경에서 서버 컴포넌트를 사용하면 클라이언트 측에서 전혀 자바스크립트가 실행되지 않으므로 하이드레이션 과정 자체가 필요 없어져 TBT와 자바스크립트 페이로드를 획기적으로 줄일 수 있습니다 [8].
## 🔗 Knowledge Connections
- **Related Topics:** [[Hydration]], [[Critical Rendering Path (CRP)]], [[Server-Side Rendering (SSR)]], [[React Server Components]]
- **Projects/Contexts:** [[Next.js]], [[Lighthouse]]
- **Contradictions/Notes:** 소스의 내용 간 상충되는 부분은 없으며, 모든 소스가 자바스크립트의 과도한 실행이 메인 스레드를 차단하여 TBT를 악화시킨다는 점에 동의합니다. 또한, 이를 방지하기 위해 렌더링 최적화(점진적 하이드레이션, 서버 컴포넌트 사용 등)가 필수적임을 강조합니다.
---
*Last updated: 2026-04-25*
@@ -0,0 +1,24 @@
# [[Virtual DOM]]
## 📌 Brief Summary
Virtual DOM(VDOM)은 메모리에 유지되는 가볍고 이상적인 UI의 표현(보통 React 엘리먼트 형태의 단순한 JavaScript 객체)을 의미합니다 [1-3]. React와 같은 라이브러리에 의해 실제 DOM과 동기화되며, 이 과정을 '재조정(Reconciliation)'이라고 부릅니다 [1-3]. 이는 개발자가 수동으로 DOM을 업데이트하고 속성을 조작하는 비효율성을 추상화하여, 선언적인 UI 개발을 가능하게 하는 핵심 프로그래밍 개념입니다 [1, 3].
## 📖 Core Content
* **DOM 조작의 비효율성 해결:**
실제 브라우저의 DOM을 직접 수정하는 작업은 본질적으로 느립니다. DOM 변경은 브라우저의 중요 렌더링 경로(Critical Rendering Path)에 있는 레이아웃(Reflow)과 페인트(Repaint) 단계를 반복적으로 트리거하기 때문입니다 [1]. 복잡한 애플리케이션에서 여러 노드를 개별적으로 업데이트하면 과도한 재계산이 발생하게 됩니다 [1]. Virtual DOM은 실제 DOM이 업데이트될 필요가 없는 경우를 걸러내어, 이러한 무거운 렌더링 과정을 최소화함으로써 브라우저 렌더링을 최적화합니다 [1, 4].
* **재조정(Reconciliation)과 Diffing 알고리즘:**
상태가 변경되면 React는 메모리상에서 이전 버전의 Virtual DOM과 새로운 Virtual DOM을 비교(diff)하여 변경 사항을 감지합니다 [2, 5]. 두 트리를 비교하는 일반적인 알고리즘은 $O(n^3)$의 복잡도를 가지지만, React는 엘리먼트의 타입이 다르면 트리를 새로 구축하고 자식 요소들은 `key` 속성을 통해 식별한다는 두 가지 가정을 기반으로 $O(n)$ 복잡도의 휴리스틱(heuristic) 알고리즘을 사용합니다 [6-8]. 이를 통해 실제 DOM을 업데이트하는 데 필요한 최소한의 연산만 수행합니다 [1].
* **Virtual DOM의 범위와 구현체:**
React 세계에서 Virtual DOM은 주로 UI를 나타내는 'React 엘리먼트' 객체를 지칭하지만, React 16부터 도입된 새로운 재조정 엔진이자 컴포넌트 트리에 대한 추가 정보를 담고 있는 내부 객체인 '파이버(Fiber)' 역시 Virtual DOM 구현의 일부로 간주됩니다 [9, 10].
* **Shadow DOM과의 차이점:**
Virtual DOM은 웹 컴포넌트의 변수 및 CSS 스코핑을 위해 설계된 브라우저 기술인 Shadow DOM과 다릅니다. Virtual DOM은 브라우저 API 위에 JavaScript 라이브러리를 통해 구현된 프로그래밍 개념입니다 [9].
## 🔗 Knowledge Connections
- **Related Topics:** [[Reconciliation]], [[DOM]], [[Critical Rendering Path]], [[Reflow / Repaint]], [[Fiber Architecture]]
- **Projects/Contexts:** [[React Performance Optimization]]
- **Contradictions/Notes:**
- Virtual DOM이 실제 DOM의 불필요한 업데이트를 방지하여 성능을 최적화하지만, 이전 Virtual DOM과 새로운 Virtual DOM을 비교하는 Diffing 작업 자체에 비용이 전혀 없는 것은 아닙니다 [4]. 무분별한 렌더링이 발생하면 이 비교 작업 자체가 컴퓨팅 오버헤드를 발생시킬 수 있습니다.
- 구현상 Virtual DOM 트리는 설계적으로 불변성(immutable)을 띠도록 다루어집니다 [11].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,25 @@
# [[“React가 빠른 이유”]]
## 📌 Brief Summary
React가 빠른 핵심적인 이유는 메모리 상에 가벼운 가상 DOM(Virtual DOM)을 두어, 브라우저의 무거운 렌더링 작업인 레이아웃(Reflow)과 페인트(Repaint)를 유발하는 실제 DOM 조작을 최소화하기 때문입니다 [1, 2]. 더불어 O(n) 복잡도의 휴리스틱 Diffing 알고리즘 [3], 렌더링 작업을 잘게 쪼개 우선순위를 관리하는 Fiber 아키텍처 [4, 5], 여러 상태 업데이트를 한 번에 묶어 처리하는 자동 일괄 처리(Automatic Batching) [6, 7] 등의 최적화 기술이 결합되어 불필요한 연산을 막고 애플리케이션의 반응성을 극대화합니다.
## 📖 Core Content
* **가상 DOM(Virtual DOM)과 휴리스틱 Diffing 알고리즘**
실제 DOM을 직접 수정하는 것은 브라우저의 Critical Rendering Path(레이아웃 및 페인트)를 거쳐야 하므로 본질적으로 매우 느립니다 [1]. 이를 해결하기 위해 React는 UI 상태를 메모리에 가벼운 객체 형태로 표현하는 가상 DOM을 도입했습니다 [1, 2]. 재조정(Reconciliation) 단계에서 이전 가상 DOM과 새로운 가상 DOM을 비교할 때, React는 두 요소의 타입이 다르면 트리를 완전히 새로 구축하고, 같은 타입이면 변경된 속성만 업데이트하는 O(n) 복잡도의 휴리스틱 알고리즘을 사용합니다 [3, 8, 9]. 이를 통해 실제 DOM 노드를 최대한 보존하며 꼭 필요한 최소한의 부분만 효율적으로 업데이트합니다 [1, 10].
* **Fiber 아키텍처와 동시성 렌더링(Concurrent Rendering)**
초기 React의 동기적이고 차단되는(blocking) 렌더링 프로세스 한계를 극복하기 위해 도입된 Fiber 아키텍처는 렌더링 작업을 'Fiber 노드'라는 작은 단위로 쪼갭니다 [4, 5, 10]. 이 아키텍처는 렌더링을 중단 및 재개 가능한 'Render 단계'와 동기적으로 DOM을 변이하는 'Commit 단계'로 분리합니다 [11, 12]. 사용자 입력과 같은 긴급한 작업에 우선순위(Lane 모델)를 부여하여 먼저 처리할 수 있도록 제어권을 브라우저에 양보하므로, 복잡한 업데이트 중에도 UI가 멈추지 않고 매끄럽게 동작합니다 [4, 13, 14].
* **자동 일괄 처리(Automatic Batching)**
React 18부터 적용된 자동 일괄 처리는 이벤트 핸들러, Promise, setTimeout 등 모든 출처에서 발생하는 다수의 상태 업데이트를 단일 리렌더링으로 묶어서(Batch) 처리합니다 [6, 7, 15]. 이는 가상 DOM의 Diffing 연산 횟수를 최소화하고, CPU 작업량과 실제 DOM의 재렌더링을 크게 줄여 성능을 향상시킵니다 [16].
* **React Compiler를 통한 렌더링 폭포(Re-render Cascade) 방지**
부모 컴포넌트의 상태가 변할 때 props 변경 여부와 상관없이 모든 자식이 재렌더링되는 현상은 React 성능 저하의 주된 원인입니다 [17]. React 19의 컴파일러는 빌드 타임에 AST(추상 구문 트리)를 분석하여 데이터 흐름을 파악하고, 불필요한 재렌더링 및 비싼 계산을 건너뛰도록 최적의 메모이제이션(Memoization) 코드를 자동으로 삽입하여 처리 속도를 대폭 높입니다 [18-21].
* **React Server Components (RSC)의 도입**
무거운 렌더링 로직이나 데이터 페칭 작업을 브라우저(클라이언트)가 아닌 서버에서 독점적으로 실행하게 합니다 [22, 23]. 이를 통해 클라이언트로 전송되는 JavaScript 번들 크기를 사실상 0바이트로 줄이고, 상호작용하기까지의 시간(INP)을 획기적으로 낮춰 초기 렌더링 속도와 체감 성능을 향상시킵니다 [24-26].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Reconciliation]], [[Fiber Architecture]], [[Automatic Batching]], [[React Compiler]], [[React Server Components]], [[Reflow / Repaint 최소화 방법]]
- **Projects/Contexts:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[렌더링 최적화 개념 설명 자료]]
- **Contradictions/Notes:** 소스에 따르면 가상 DOM이 불필요한 실제 DOM 업데이트를 막아주기는 하지만, 가상 DOM 트리를 비교(Diffing)하는 연산 자체도 무료가 아닙니다 [27]. 따라서 가상 DOM 메커니즘 하나만으로 속도가 무조건 보장되는 것은 아니며, 'Automatic Batching'이나 컴포넌트의 불필요한 연산을 막는 'React Compiler(또는 수동 메모이제이션)' 같은 기술이 병행되어야 가상 DOM의 Diffing 오버헤드까지 잡아내어 진정한 속도 최적화를 이룰 수 있습니다 [16, 20, 27, 28].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,28 @@
# [[검색 엔진 최적화(SEO) 대응 렌더링 전략 수립]]
## 📌 Brief Summary
검색 엔진 최적화(SEO) 대응 렌더링 전략은 웹 애플리케이션의 콘텐츠가 검색 엔진 크롤러에 의해 효과적으로 색인(Index)될 수 있도록 서버 및 클라이언트의 렌더링 방식을 설계하는 과정입니다. 검색 엔진 봇은 주로 초기 HTML을 수집하므로, 자바스크립트 실행 전 비어 있는 페이지를 제공하는 클라이언트 사이드 렌더링(CSR)은 SEO에 불리할 수 있습니다 [1-3]. 따라서 프로젝트의 콘텐츠 성격, 업데이트 빈도, 보안 요구사항에 맞춰 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG) 등의 방식을 적절히 혼합하여 최적의 검색 가시성과 성능을 확보하는 것이 핵심입니다 [4-7].
## 📖 Core Content
* **CSR(Client-Side Rendering)의 SEO 한계**
CSR은 서버로부터 최소한의 빈 HTML과 자바스크립트 번들을 먼저 받아 브라우저에서 동적으로 UI를 생성합니다 [1, 8-10]. 최신 검색 엔진 크롤러의 자바스크립트 처리 능력이 과거에 비해 다소 개선되었음에도 불구하고, 여전히 콘텐츠 렌더링 전에 빈 페이지만을 인식할 위험이 커서 색인이 지연되거나 누락될 수 있습니다 [1-3, 11]. 따라서 CSR은 SEO가 중요하지 않고 풍부한 상호작용이 필요한 비공개 대시보드나 SaaS 플랫폼에 주로 적합합니다 [12-14].
* **SSR(Server-Side Rendering)을 통한 즉각적인 콘텐츠 제공**
SSR은 요청이 발생할 때마다 서버에서 전체 HTML을 렌더링하여 클라이언트와 크롤러에 전송합니다 [15-17]. 크롤러가 자바스크립트 실행(Hydration)을 기다리지 않고도 구조화된 콘텐츠를 즉시 수집할 수 있으므로 SEO 성능을 크게 향상시킵니다 [6, 15, 18-21]. 또한 메타 태그와 Open Graph 데이터를 온전히 제공하여 소셜 미디어 공유 시 풍부한 미리보기를 생성하는 데 유리합니다 [20, 22]. SSR은 뉴스 사이트나 전자상거래 상품 목록 등 실시간 최신 데이터를 유지하면서 높은 검색 가시성이 필요한 곳에 이상적입니다 [23-25].
* **SSG(Static Site Generation)와 사전 렌더링의 강점**
SSG는 빌드 시점에 모든 페이지의 HTML을 미리 생성해 CDN을 통해 배포합니다 [26-29]. 크롤러는 대기 시간이나 서버 측 연산 없이 완벽하게 구성된 HTML을 즉시 전달받게 되므로 검색 순위와 검색 가능성이 극대화됩니다 [6, 30, 31]. 블로그, 공식 문서, 마케팅 랜딩 페이지 등 변경이 잦지 않은 정적 콘텐츠 웹사이트에 완벽한 렌더링 전략입니다 [27, 32-34].
* **ISR(Incremental Static Regeneration)을 이용한 균형 잡힌 성능**
ISR은 SSG의 초고속 성능을 유지하면서 정해진 시간 간격(예: 60초)이나 필요에 따라 백그라운드에서 특정 페이지를 재생성하여 최신 상태로 업데이트합니다 [26, 35-38]. 대규모 전자상거래의 상품 카탈로그처럼 수많은 페이지에 대해 빠른 초기 로드 속도와 SEO 친화적인 정적 HTML을 제공함과 동시에 주기적인 콘텐츠 업데이트가 필요한 경우 가장 효율적으로 동작합니다 [14, 24, 39].
* **페이지 맞춤형 혼합(Hybrid) 렌더링 전략의 채택**
현대적인 웹 애플리케이션 프레임워크(예: Next.js, Nuxt)를 사용하면 전체 애플리케이션에 단일 전략을 고집할 필요가 없습니다 [4, 40, 41]. 홈페이지와 문서에는 가장 빠른 SSG를, 실시간 재고나 최신 뉴스가 필요한 페이지에는 SSR을, 로그인된 사용자 전용 대시보드에는 CSR을 적용하는 방식으로 페이지별 SEO 중요도 및 동적 요구사항에 맞춰 렌더링 방식을 혼합 구성하는 것이 권장됩니다 [4, 7, 41].
## 🔗 Knowledge Connections
- **Related Topics:** `[[CSR vs SSR vs SSG]]`, `[[Hydration]]`, `[[React Server Components]]`, `[[Critical Rendering Path]]`
- **Projects/Contexts:** `[[대규모 이커머스 플랫폼 렌더링 설계]]`, `[[SEO 중심의 마케팅 및 블로그 사이트 구축]]`
- **Contradictions/Notes:** 소스 [2]에서는 검색 엔진이 과거보다 자바스크립트를 크롤링하는 능력이 향상되었다고 언급하지만, 소스 [3, 11, 42] 등에서는 여전히 크롤러가 자바스크립트를 올바르게 실행하는 데 어려움을 겪거나 초기 빈 HTML만을 읽어 콘텐츠가 누락되는 치명적인 한계가 존재한다고 주장합니다. 따라서 SEO가 핵심인 서비스에서는 순수 CSR에 의존하지 않는 것이 일반적인 합의입니다.
---
*Last updated: 2026-04-25*
@@ -0,0 +1,35 @@
# [[단일 페이지 애플리케이션(SPA) 아키텍처 설계]]
## 📌 Brief Summary
단일 페이지 애플리케이션(SPA)은 서버로부터 최소한의 HTML 껍데기와 JavaScript 번들을 제공받은 후, 브라우저에서 동적으로 UI를 구성하고 렌더링하는 클라이언트 사이드 렌더링(CSR) 방식을 주로 활용하는 프론트엔드 아키텍처입니다 [1-4]. 초기 다운로드 크기가 커서 로딩이 느릴 수 있지만, 페이지가 로드된 이후에는 전체 페이지 새로고침 없이 부분적인 데이터만 업데이트하여 매끄럽고 상호작용성이 뛰어난 사용자 경험을 제공합니다 [5-8]. 현대의 SPA는 이러한 CSR의 단점을 극복하기 위해 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG), 그리고 컴포넌트 기반 아키텍처(CBA)와 같은 전략들을 혼합하여 성능과 확장성을 최적화합니다 [9, 10].
## 📖 Core Content
**브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)**
브라우저의 중요 렌더링 경로(Critical Rendering Path)는 HTML을 점진적으로 파싱하여 DOM(Document Object Model) 트리를 구축하고, CSS를 파싱하여 렌더링 차단 리소스인 CSSOM(CSS Object Model)을 생성하는 것으로 시작됩니다 [11-14]. DOM과 CSSOM이 준비되면 이 둘을 결합하여 렌더 트리(Render Tree)를 형성합니다. 렌더 트리는 `<script>``display: none`이 적용된 요소와 같이 화면에 보이지 않는 노드를 제외하고, 가시적인 노드와 그에 일치하는 계산된 스타일 정보만을 포함합니다 [15-18]. 이후 각 시각적 요소의 정확한 크기와 뷰포트 내 위치를 계산하는 레이아웃(Layout/Reflow) 단계를 거쳐, 픽셀을 화면에 그리는 페인트(Paint/Repaint)와 여러 레이어를 화면에 결합하는 합성(Compositing) 과정을 통해 UI가 표시됩니다 [19-23].
**Reflow / Repaint 최소화 방법**
Reflow(레이아웃)는 DOM 구조가 변경되거나 창 크기 조정, 마진, 너비, 높이 등의 기하학적 속성이 변경될 때 트리의 상당 부분을 다시 계산해야 하므로 컴퓨팅 자원을 크게 소모합니다 [24-27]. Repaint는 색상이나 그림자 등 시각적 스타일만 변경될 때 발생합니다 [24, 25, 27]. 성능 최적화를 위해서는 불필요한 DOM 트리의 깊이를 줄이고, CSS 규칙을 간소화하며, DOM 업데이트를 일괄 처리(batching)해야 합니다 [28-30]. 특히 애니메이션 요소는 `top`이나 `left` 대신 `transform``opacity` 속성을 사용하여, 브라우저가 요소를 독립적인 레이어로 분리하고 GPU 가속(Compositing)을 활용하게 함으로써 Reflow를 피하는 것이 핵심입니다 [20, 29-31].
**DOM vs Virtual DOM 및 React가 빠른 이유**
전통적인 방식처럼 DOM을 직접 수정하면 레이아웃과 페인트 연산이 반복적으로 트리거되어 성능이 크게 저하됩니다 [32]. React는 이를 극복하기 위해 UI의 가벼운 메모리 내 표현인 가상 DOM(Virtual DOM)을 사용합니다 [32-34]. React는 컴포넌트의 상태가 변할 때마다 새로운 가상 DOM을 생성하고, 이전 상태와 비교하는 $O(n)$ 복잡도의 휴리스틱 기반 Diffing 알고리즘(Reconciliation)을 실행하여 실제 변경된 속성이나 노드만 선별적으로 실제 DOM에 패치(업데이트)합니다 [32, 33, 35-37].
여기에 더해 React 16부터 도입된 파이버(Fiber) 아키텍처는 동시성 렌더링을 가능하게 합니다. 렌더링 작업을 중단, 재개, 혹은 폐기할 수 있는 작은 '작업 단위'로 분할하고, 사용자 입력이나 클릭과 같은 긴급한 작업을 데이터 필터링 같은 작업보다 우선 처리(우선순위 Lane 모델)하여 화면 버벅임(Jank)을 방지하고 반응성을 유지합니다 [38-44].
**렌더링 최적화 개념 (자동 일괄 처리 및 React Compiler)**
최신 React는 성능 병목을 프레임워크 단에서 해결하고 있습니다. React 18의 자동 일괄 처리(Automatic Batching)는 기존 이벤트 핸들러뿐 아니라 `setTimeout`이나 `Promise` 같은 비동기 작업에서 발생하는 다수의 상태 업데이트를 하나의 리렌더링으로 묶어 DOM 렌더링 횟수를 획기적으로 줄여줍니다 [45-48]. 더 나아가, React 19에 도입된 React Compiler는 빌드 단계에서 코드를 정적 분석하여 변경되지 않는 값과 컴포넌트에 메모이제이션을 자동 삽입합니다. 이로 인해 불필요한 재렌더링(Re-render Cascade)이 제거되고 개발자가 수동으로 `useMemo`, `useCallback`, `React.memo`를 작성해야 하는 인지적 부담이 사라집니다 [49-53].
**CSR vs SSR vs SSG 렌더링 전략 비교**
- **CSR (Client-Side Rendering):** 클라이언트(브라우저)에서 JavaScript를 실행해 전체 UI를 구축하고 데이터를 가져옵니다. 매우 동적인 상호작용을 지원하지만, 초기 렌더링까지 사용자가 빈 화면을 보게 되며 자바스크립트 실행이 필수적이라 검색 엔진 최적화(SEO)에 불리할 수 있습니다 [1, 2, 5, 54-57].
- **SSR (Server-Side Rendering):** 서버가 각 요청마다 데이터가 포함된 완전한 HTML을 렌더링하여 클라이언트에게 전송합니다. SEO에 매우 유리하며 초기 콘텐츠 페인트(FCP)가 빠르지만, 사용자 인터랙션을 위해 JavaScript 번들을 다운받고 연결하는 '하이드레이션(Hydration)' 과정 동안 입력 지연(TTI 지연)이 발생할 수 있습니다 [58-63].
- **SSG (Static Site Generation) & ISR (Incremental Static Regeneration):** 빌드 타임에 HTML을 생성하여 CDN으로 배포하는 방식으로 성능 면에서 가장 빠르나 잦은 데이터 변경에는 취약합니다(SSG). ISR은 이를 보완하여 주기적으로 정적 페이지를 백그라운드에서 재생성합니다 [64-70].
- **React Server Components (RSC):** 컴포넌트를 서버에서만 실행하고 직렬화된 데이터만을 클라이언트에 스트리밍하여 전송하는 혁신적 모델입니다. 클라이언트 자바스크립트 번들 크기에 전혀 영향을 주지 않고 서버 리소스(DB 등)에 직접 접근할 수 있게 해, 복잡한 프론트엔드 환경에서 상호작용이 필요한 클라이언트 컴포넌트(Client Component)와 역할을 명확히 분리합니다 [71-76].
**컴포넌트 기반 아키텍처 (Component-Based Architecture)**
최신의 단일 페이지 애플리케이션 설계는 시스템을 분리 가능하고 재사용 가능한 소프트웨어 조각(컴포넌트)으로 구성하는 CBA 방법론을 따릅니다 [77-79]. 각 컴포넌트는 특정한 상태와 UI 로직을 캡슐화(Encapsulation)하여 잘 정의된 인터페이스(Props 등)로 통신합니다 [77, 80]. 이 구조는 코드의 모듈성과 재사용성을 높이고 유지보수와 디버깅을 단순화하며, 여러 개발팀이 독립적으로 기능(예: 검색창, 장바구니 등)을 개발하여 빠르고 유연하게 확장할 수 있는 기반이 됩니다 [81-85].
## 🔗 Knowledge Connections
- **Related Topics:** [[브라우저 렌더링 프로세스 (CRP)]], [[가상 DOM (Virtual DOM) 및 재조정(Reconciliation)]], [[React Fiber 및 동시성 렌더링]], [[서버 사이드 렌더링(SSR)과 하이드레이션(Hydration)]], [[컴포넌트 기반 아키텍처 (CBA)]]
- **Projects/Contexts:** [[Next.js를 활용한 하이브리드 렌더링 및 React Server Components 도입]], [[React 18 자동 일괄 처리 및 React 19 컴파일러 최적화 적용]]
- **Contradictions/Notes:** CSR 방식은 초기 로드 속도와 SEO 측면에서 불리하다는 한계가 널리 알려져 있으나, 실시간 상호작용이 많고 SEO가 중요하지 않은 인증 기반의 SaaS 대시보드나 내부 비즈니스 도구에서는 서버의 렌더링 부하를 줄이고 유연성을 높이기 때문에 여전히 SSR보다 가장 적합한 렌더링 방식으로 권장됩니다 [4, 86, 87]. 또한, React 19 컴파일러가 대부분의 수동 메모이제이션을 불필요하게 만들지만, 외부 타사 라이브러리 연동 시 참조 안정성이 깨지거나 이펙트 의존성 제어가 필요한 특정 상황에서는 여전히 `useMemo` 등을 통한 수동 제어가 필요할 수 있습니다 [88-90].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,28 @@
# [[렌더링 최적화 개념 설명 자료]]
## 📌 Brief Summary
렌더링 최적화는 브라우저가 HTML, CSS, JavaScript를 화면의 픽셀로 변환하는 '중요 렌더링 경로(Critical Rendering Path)'를 효율적으로 수행하도록 구성하여 초기 로딩 속도와 상호작용의 반응성을 극대화하는 작업입니다 [1]. 브라우저 관점에서는 연산 비용이 큰 리플로우(Reflow)와 리페인트(Repaint)를 줄이고 GPU 하드웨어 가속을 활용하며, React 환경에서는 불필요한 리렌더링을 차단하고 렌더링 작업의 우선순위를 관리하여 메인 스레드의 부하를 최소화하는 것이 핵심입니다 [2-5].
## 📖 Core Content
* **중요 렌더링 경로(CRP) 최적화:**
브라우저는 HTML 및 CSS를 파싱하여 DOM과 CSSOM 트리를 생성하고, 이 둘을 결합해 시각적 정보만 담은 렌더 트리(Render Tree)를 구축한 후, 레이아웃과 페인트 단계를 거쳐 화면을 렌더링합니다 [1, 6, 7]. 렌더링 성능을 높이려면 렌더링을 차단하는 리소스(CSS, 동기식 JavaScript)의 다운로드를 비동기화하거나 지연시키고, 렌더 트리에 포함되는 불필요한 DOM 노드 개수와 CSS 선택자의 복잡성을 줄여 브라우저의 처리량을 최소화해야 합니다 [4, 8, 9].
* **리플로우(Reflow) 및 리페인트(Repaint) 최소화:**
* **리플로우(레이아웃) 방지:** 요소의 기하학적 속성(너비, 높이, 마진 등)이 변경될 때 발생하는 리플로우는 문서 전체의 레이아웃을 다시 계산하게 만들어 연산 비용이 매우 큽니다 [10, 11]. DOM 변경은 일괄 처리(batching)하여 레이아웃 스래싱(Layout Thrashing)을 방지하고, 복잡한 애니메이션 요소는 `position: absolute` 또는 `fixed` 속성을 적용해 문서 흐름(flow)에서 분리해야 합니다 [2, 9, 12].
* **리페인트 감소 및 하드웨어 가속:** 시각적 속성(색상, 그림자 등)만 바뀔 때는 리페인트가 발생합니다 [2, 11]. 애니메이션을 구현할 때 `transform`, `opacity` 속성을 사용하면 브라우저가 요소를 별도의 레이어로 승격시켜 CPU가 아닌 GPU에서 합성(Compositing) 작업을 처리하게 하므로, 리플로우와 리페인트를 모두 피하고 성능을 획기적으로 개선할 수 있습니다 [3, 13, 14].
* **DOM 조작 및 상호작용 최적화:**
DOM에 반복적으로 접근하는 것은 처리 속도를 저하시키므로 DOM 노드나 속성값을 캐싱하여 반복문 외부에서 다루어야 합니다 [12, 15]. DOM에 노드를 반복 추가하는 대신 HTML 문자열을 일괄 교체하고, 개별 요소마다 이벤트 핸들러를 등록하는 대신 상위 노드에 이벤트를 위임하는 '이벤트 위임(Event Delegation)' 기법을 적용하여 리소스를 절약해야 합니다 [16, 17].
* **React 환경에서의 렌더링 최적화:**
* **리렌더링 차단 연산:** React는 부모 컴포넌트의 상태가 변하면 하위 컴포넌트가 모두 리렌더링되는 폭포수(Cascade) 현상이 발생합니다 [18]. 이를 방지하기 위해 `React.memo`, `useMemo`, `useCallback`을 활용해 참조와 결과를 메모이제이션하여 불필요한 가상 DOM 연산을 생략합니다 [19, 20]. 인라인 객체 및 함수 생성은 참조를 새롭게 만들어 메모이제이션을 무효화하므로 피해야 합니다 [21].
* **자동 배칭 및 동시성 렌더링:** React 18에서 기본 활성화된 자동 배칭(Automatic Batching)은 비동기 작업 및 이벤트 핸들러 내의 여러 상태 업데이트를 묶어 단일 리렌더링으로 처리해 성능을 크게 높입니다 [22, 23]. 또한 `useTransition``useDeferredValue` 훅을 사용하면 무거운 작업의 렌더링 우선순위를 낮춰, 긴급한 사용자 입력 등에 메인 스레드를 양보할 수 있습니다 [24, 25].
* **구조적 아키텍처 개선:** 항목이 많은 리스트에는 화면에 보이는 노드만 렌더링하는 가상화(Virtualization) 기술을 적용하고 [26], 빈번하게 변경되는 전역 상태는 Context를 세분화하여 상태를 구독하는 컴포넌트의 불필요한 렌더링 범위를 축소해야 합니다 [27].
## 🔗 Knowledge Connections
- **Related Topics:** [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]], [[DOM vs Virtual DOM]], [[CSR vs SSR vs SSG]], [[Reflow / Repaint 최소화 방법]], [[React가 빠른 이유]]
- **Projects/Contexts:** [[컴포넌트 기반 아키텍처 개념 수집 포인트]]
- **Contradictions/Notes:** React에서 메모이제이션(`React.memo`, `useMemo` 등)은 보편적인 해결책이 될 수 없습니다. 모든 컴포넌트를 감싸는 것은 얕은 비교를 위한 연산 비용과 메모리 오버헤드를 발생시키므로, 렌더링에 시간이 지연되는 컴포넌트(5~10ms 이상 소요)에만 프로파일링 후 선택적으로 적용해야 합니다 [28]. 또한 React 19의 React Compiler를 사용하면 수동 메모이제이션 작업의 대부분을 빌드 도구가 자동으로 대신 처리할 수 있습니다 [29].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,31 @@
# [[브라우저 렌더링 과정 (HTML → CSSOM → Render Tree)]]
## 📌 Brief Summary
브라우저 렌더링 과정, 또는 중요 렌더링 경로(Critical Rendering Path)는 브라우저가 HTML, CSS, JavaScript 코드를 화면의 픽셀로 변환하기 위해 거치는 일련의 단계입니다 [1, 2]. 브라우저는 HTML을 파싱하여 DOM 트리를 만들고 CSS를 파싱하여 CSSOM 트리를 생성한 후, 두 트리를 결합하여 화면에 표시될 요소만 포함된 Render Tree(렌더 트리)를 구축합니다 [2, 3]. 이후 각 요소의 정확한 크기와 위치를 계산하는 Layout(레이아웃) 단계를 거쳐, 최종적으로 화면에 픽셀을 그리는 Paint(페인트) 작업을 수행하게 됩니다 [3, 4]. 이 과정을 최적화하는 것은 초기 로딩 속도를 높이고 끊김 없는 상호작용을 제공하는 프론트엔드 성능 관리의 핵심입니다 [5, 6].
## 📖 Core Content
- **DOM(Document Object Model) 구축 단계**
브라우저는 서버로부터 HTML 데이터를 수신하면 점진적(incremental) 파싱을 시작하여 바이트를 문자, 토큰, 노드로 순차적으로 변환하고 최종적으로 DOM 트리 구조를 구축합니다 [1, 7, 8]. DOM 트리는 문서의 구조와 콘텐츠를 나타내며, 파싱 과정이 점진적으로 이루어지기 때문에 브라우저는 네트워크 요청이 진행되는 중에도 트리 생성을 시작할 수 있습니다 [7, 9].
- **CSSOM(CSS Object Model) 구축 단계**
DOM이 콘텐츠를 나타낸다면 CSSOM은 콘텐츠의 스타일과 규칙을 정의합니다 [9, 10]. DOM 구축과 달리 CSSOM 구축은 렌더링 차단(render-blocking) 작업입니다 [9, 10]. 브라우저는 스타일이 지정되지 않은 날 것의 HTML이 화면에 노출되는 현상(FOUC)을 방지하기 위해, 모든 링크된 스타일시트를 다운로드하고 파싱할 때까지 렌더 트리 구성을 차단합니다 [9, 10]. CSS의 계단식(Cascade) 특성 때문에 후속 규칙이 이전 규칙을 덮어쓸 수 있어 이 과정은 점진적으로 화면에 렌더링할 수 없습니다 [11, 12].
- **Render Tree (렌더 트리) 생성**
DOM과 CSSOM 트리가 모두 준비되면 브라우저는 이 둘을 결합하여 렌더 트리를 만듭니다 [13, 14]. 렌더 트리는 화면에 렌더링하는 데 필요한 시각적 노드들만 포함하는 정제된 트리입니다 [3, 13]. `<script>`, `<meta>` 태그나 `display: none` 스타일이 적용된 노드는 시각적 레이아웃에 영향을 주지 않으므로 렌더 트리에서 완전히 제외됩니다 [3, 13-15]. 단, 공간을 차지하는 `visibility: hidden` 요소는 렌더 트리에 포함됩니다 [16, 17].
- **Layout (레이아웃 또는 Reflow)**
렌더 트리가 완성되면 브라우저는 뷰포트 크기와 박스 모델을 기반으로 화면에 표시될 각 요소의 정확한 기하학적 위치(x, y)와 크기(너비, 높이)를 계산합니다 [18-21]. 창 크기를 조절하거나 JavaScript로 요소의 크기 및 위치를 변경하는 작업은 트리 전체에 걸친 연쇄적인 재계산을 유발할 수 있으며, 이 비용이 많이 드는 계산 과정을 보통 'Reflow(리플로우)'라고 부릅니다 [18, 19, 22].
- **Paint (페인트 또는 Repaint) 및 Compositing (합성)**
레이아웃 계산이 완료되면 계산된 기하학적 구조와 스타일(색상, 그림자, 텍스트 등)을 실제 픽셀로 변환하여 그리는 Paint 단계로 넘어갑니다 [19, 23-25]. 시각적 속성만 변경되어 레이아웃 재계산 없이 화면을 다시 그리는 과정은 'Repaint(리페인트)'라고 합니다 [23, 26]. 마지막 단계인 합성(Compositing)에서는 렌더링 엔진이 개별 레이어를 단일 이미지로 결합하여 화면에 출력하며, 애니메이션 등 특정 작업은 GPU 연산을 활용하여 성능을 높일 수 있습니다 [19, 23, 27, 28].
- **React 아키텍처와의 연관성**
수동으로 DOM을 직접 조작하는 것은 본질적으로 느리며 이 과정에서 불필요한 Reflow와 Repaint를 빈번하게 유발하여 화면의 버벅거림(Jank)을 초래합니다 [23, 29, 30]. React와 같은 프레임워크는 이러한 브라우저 렌더링 엔진의 구조적 한계와 비효율성을 극복하기 위해 메모리 내에 가벼운 UI 복사본인 [[Virtual DOM]]을 도입하였으며, 변경 사항을 모아 효율적으로 실제 DOM을 업데이트함으로써 렌더링 최적화를 이룹니다 [5, 29].
## 🔗 Knowledge Connections
- **Related Topics:** [[Virtual DOM]], [[Reflow 및 Repaint]], [[Critical Rendering Path (CRP)]]
- **Projects/Contexts:** [[프론트엔드 성능 최적화 전략]], [[React 컴포넌트 기반 아키텍처]]
- **Contradictions/Notes:** 소스에 따르면 HTML의 DOM 파싱은 점진적(incremental)으로 이루어지는 반면, CSSOM 구성은 스타일 덮어쓰기 문제 때문에 완료될 때까지 브라우저 화면 출력을 막는 렌더링 차단(render-blocking) 특성을 가집니다 [7, 9-11].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,32 @@
# [[브라우저 렌더링 과정 최적화 및 UI 반응성 개선]]
## 📌 Brief Summary
브라우저 렌더링 과정은 브라우저가 HTML, CSS, JavaScript를 파싱하여 DOM과 CSSOM을 구축하고, 이를 기반으로 렌더 트리를 생성한 뒤 화면에 픽셀을 그리는 일련의 경로(Critical Rendering Path)를 의미합니다 [1, 2]. 이 과정에서 발생하는 불필요한 레이아웃 재계산(Reflow)과 화면 다시 그리기(Repaint)는 성능을 저하시키는 주요 원인이 되므로 이를 최소화하는 것이 필수적입니다 [3-6]. 현대의 프론트엔드 환경에서는 이러한 비용을 줄이고 UI 반응성을 극대화하기 위해 React의 Virtual DOM, Fiber 아키텍처, 자동 배칭(Automatic Batching), 그리고 React Compiler와 같은 고도화된 최적화 기술들이 활용되고 있습니다 [7-11].
## 📖 Core Content
**1. 브라우저 렌더링의 핵심 경로 (Critical Rendering Path)**
* **파싱 및 트리 구축:** 브라우저는 서버로부터 받은 HTML을 점진적으로 파싱하여 문서의 구조를 나타내는 DOM(Document Object Model) 트리를 구축합니다 [1, 12-14]. 동시에 CSS를 파싱하여 스타일 정보를 담은 CSSOM(CSS Object Model) 트리를 생성하는데, CSSOM은 구축이 완료될 때까지 렌더링을 차단(Render-blocking)하는 특성을 가집니다 [15, 16].
* **렌더 트리(Render Tree) 생성:** DOM과 CSSOM이 준비되면, 브라우저는 화면에 시각적으로 표시될 노드들만 모아 렌더 트리를 합성합니다 [2, 17, 18]. (`<script>` 태그나 `display: none` 스타일이 적용된 요소는 제외됩니다 [17, 18].)
* **레이아웃(Layout)과 페인트(Paint):** 렌더 트리를 기반으로 기기 뷰포트에 맞춰 각 요소의 정확한 크기와 위치를 계산하는 레이아웃 과정을 거칩니다 [19-22]. 이후 변환된 기하학적 정보를 실제 화면의 픽셀로 변환하여 그리는 페인트(Paint) 단계와, 레이어들을 하나로 합치는 합성(Compositing) 단계가 수행됩니다 [23-25].
**2. 리플로우(Reflow)와 리페인트(Repaint) 최소화**
* **성능 비용:** 요소의 너비, 높이, 마진 등을 변경하거나 DOM 구조를 조작하면, 브라우저는 레이아웃을 다시 계산하는 리플로우(Reflow)를 발생시킵니다 [5, 19, 26]. 리플로우는 트리 전체에 걸쳐 연쇄적인 재계산을 유발할 수 있어 연산 비용이 매우 높습니다 [3, 5, 27]. 배경색이나 가시성 등 시각적 요소만 변경될 때는 레이아웃 단계 없이 리페인트(Repaint)만 발생하지만, 이 역시 과도하면 프레임 저하를 초래합니다 [6, 23, 26].
* **최적화 방법:** 불필요한 DOM 깊이를 줄이고 [28], DOM 상태 업데이트를 일괄 처리(Batching)하며 [3, 29], 애니메이션에는 레이아웃을 유발하지 않고 GPU 가속을 활용할 수 있는 `transform` 등의 속성을 사용하는 것이 권장됩니다 [6, 23, 29].
**3. React의 렌더링 최적화 아키텍처**
* **Virtual DOM과 재조정(Reconciliation):** DOM을 직접 조작하는 것은 느리기 때문에, React는 메모리에 가벼운 Virtual DOM을 유지합니다 [10, 30]. 상태 변경 시 새로운 Virtual DOM 트리를 만들고 이전 트리와 비교(Diffing)하는 휴리스틱 $O(n)$ 알고리즘을 통해, 실제 변경된 부분만 실제 DOM에 반영하여 리플로우와 리페인트를 최소화합니다 [10, 30-32].
* **Fiber 아키텍처와 동시성(Concurrent) 기능:** React 16부터 도입된 Fiber는 렌더링 작업을 'Fiber 노드' 단위로 쪼개어 중단 및 재개가 가능하게 만든 스케줄링 아키텍처입니다 [33-36]. 사용자 입력과 같은 긴급한 작업(Sync Lane)을 데이터 페칭 결과 등 덜 긴급한 작업보다 우선 처리함으로써 메인 스레드 차단을 막고 UI 반응성을 유지합니다 [37-39]. 이를 활용한 `useTransition` 훅 등은 무거운 연산 중에도 UI가 멈추지 않게 돕습니다 [7, 40, 41].
**4. 최신 React(18, 19)의 자동화된 성능 개선**
* **자동 배칭(Automatic Batching):** React 18부터는 네이티브 이벤트뿐만 아니라 비동기 작업(Promise, `setTimeout` 등) 내에서 발생하는 여러 상태 업데이트를 단일 리렌더링으로 묶어서 처리(Batching)합니다 [8, 42-44]. 이를 통해 불필요한 리렌더링 횟수를 대폭 줄여 성능을 크게 향상시킵니다 [45, 46].
* **React Compiler:** 잦은 리렌더링을 막기 위해 과거에는 개발자가 수동으로 `React.memo`, `useMemo`, `useCallback` 등을 적용해야 했습니다 [9, 47]. 하지만 React 19 컴파일러는 빌드 타임에 코드(AST)를 분석하여 데이터 흐름을 추적하고, 필요한 곳에 자동으로 세밀한 메모이제이션을 삽입해 개발자의 부담을 줄이고 렌더링을 최적화합니다 [9, 48-50].
* **React Server Components (RSC):** 클라이언트 번들 크기와 파싱/실행 시간을 줄이기 위해, 서버에서 컴포넌트를 렌더링하고 직렬화된 UI 표현만 브라우저로 스트리밍하는 구조입니다 [51-53]. 인터랙션이 필요 없는 UI를 서버 컴포넌트로 분리함으로써, 브라우저가 처리해야 할 자바스크립트 양을 줄여 로딩 속도와 INP(Interaction to Next Paint) 지표를 개선합니다 [54-56].
## 🔗 Knowledge Connections
- **Related Topics:** [[Critical Rendering Path]], [[Reflow and Repaint]], [[Virtual DOM]], [[React Fiber Architecture]], [[Automatic Batching]], [[React Compiler]], [[React Server Components]]
- **Projects/Contexts:** [[Core Web Vitals Optimization (INP, LCP 개선)]], [[Next.js 기반의 Hybrid Rendering (SSR/CSR/RSC 혼합 적용)]]
- **Contradictions/Notes:** CSS 선택자의 성능 최적화와 관련해, MDN 가이드에서는 브라우저가 매우 빠르기 때문에 선택자 성능 최적화(예: 특정성을 낮추는 작업)가 가져오는 이득이 마이크로초 단위에 불과하여 최우선 최적화 대상이 아닐 수 있다고 언급하지만 [57], 다른 구글 개발자 가이드에서는 불필요하게 복잡한 하위(descendant) 선택자를 피하는 것을 리플로우/렌더링 시간 단축을 위한 주요 지침 중 하나로 제시하고 있습니다 [28, 58].
---
*Last updated: 2026-04-25*
@@ -0,0 +1,30 @@
# [[프론트엔드 성능 최적화]]
## 📌 Brief Summary
프론트엔드 성능 최적화는 브라우저의 렌더링 과정을 이해하고, 불필요한 연산을 줄여 사용자에게 빠르고 매끄러운 웹 경험을 제공하는 일련의 과정입니다 [1, 2]. 이를 위해 HTML과 CSS가 DOM과 CSSOM을 거쳐 렌더 트리로 변환되는 중요 렌더링 경로(CRP)를 관리하며, 비용이 많이 드는 Reflow와 Repaint를 최소화합니다 [3, 4]. 또한 React의 Virtual DOM 메커니즘을 활용하여 DOM 조작을 효율화하고, 프로젝트의 목적에 맞게 CSR, SSR, SSG 등의 렌더링 방식을 전략적으로 선택하여 컴포넌트 기반 아키텍처로 유지보수성이 높은 시스템을 설계하는 것을 핵심 목적으로 합니다 [1, 5, 6].
## 📖 Core Content
* **브라우저 렌더링 과정 (HTML → CSSOM → Render Tree):**
브라우저는 데이터를 점진적으로 파싱하여 HTML을 문서 객체 모델(DOM)로 생성하고, CSS를 파싱하여 CSS 객체 모델(CSSOM)로 변환합니다 [3, 7, 8]. 이 두 트리가 준비되면 화면에 실제로 표시될 노드와 계산된 스타일 정보만을 포함하는 렌더 트리(Render Tree)로 결합합니다 (`display: none` 등의 시각적으로 숨겨진 요소는 제외됩니다) [9, 10]. 이후 렌더 트리를 기반으로 각 요소의 정확한 크기와 위치를 계산하는 레이아웃(Layout 또는 Reflow) 단계를 거친 후, 계산된 기하학적 형태를 화면의 실제 픽셀로 변환하는 페인트(Paint 또는 Repaint) 단계를 수행합니다 [11-15].
* **Reflow / Repaint 최소화 방법:**
Reflow(레이아웃 계산)는 브라우저 창 크기 조절이나 요소의 크기, 위치(`width`, `height`, `margin` 등)가 변경될 때 발생하며, 문서 흐름에 따라 전체 트리에 연쇄적인 재계산을 유발할 수 있어 연산 비용이 매우 높습니다 [11, 16-18]. 이를 최소화하려면 불필요한 DOM 깊이를 줄이고, 복잡한 CSS 선택자를 피해야 합니다 [19]. 특히 애니메이션과 같이 복잡한 렌더링 변경 시에는 `position: absolute``fixed`를 사용하여 문서 흐름에서 요소를 분리하거나, Reflow를 유발하지 않고 GPU 가속을 활용할 수 있는 `transform` 속성을 사용하는 것이 좋습니다 [4, 12, 19, 20]. Repaint는 색상이나 그림자 등 시각적 속성만 변경될 때 발생하며 Reflow보다 부담은 적지만, 과도하게 발생 시 성능을 저하시키므로 DOM 조작과 변경 사항을 일괄 처리(batching)하는 전략이 필수적입니다 [4, 12, 16, 21].
* **DOM vs Virtual DOM 및 “React가 빠른 이유”:**
실제 DOM을 직접 조작하는 것은 본질적으로 매번 레이아웃과 페인트 단계를 유발해 속도가 느립니다 [22]. React는 이를 해결하기 위해 메모리 내에 UI의 가벼운 표현인 가상 DOM(Virtual DOM)을 유지합니다 [22, 23]. 상태가 변경되면 React는 O(n) 복잡도의 휴리스틱 Diffing 알고리즘을 통해 이전 가상 트리와 새로운 가상 트리를 비교(Reconciliation)하고, 변경된 특정 속성이나 노드만을 계산해 실제 DOM에 한 번에 반영합니다 [22, 24-27]. 이처럼 불필요한 DOM 연산을 최소화하는 방식과 더불어, 렌더링 작업을 잘게 쪼개 우선순위를 매기는 Fiber 아키텍처와 상태 업데이트를 자동으로 그룹화하는 자동 일괄 처리(Automatic Batching) 기능 덕분에 React는 빠르고 반응성 높은 UI를 제공할 수 있습니다 [28-31].
* **CSR vs SSR vs SSG 렌더링 전략:**
* **CSR (Client-Side Rendering):** 서버에서 빈 HTML과 JavaScript를 보내고 브라우저가 화면을 렌더링합니다 [5, 32, 33]. 대시보드나 SaaS 앱처럼 상호작용이 많을 때 유리하지만, 자바스크립트 실행 전까지 화면이 비어 있어 초기 로딩(FCP)이 느리고 SEO에 취약합니다 [5, 34-36].
* **SSR (Server-Side Rendering):** 서버가 각 요청마다 완전한 HTML을 렌더링하여 클라이언트에 전달하므로, 초기 화면이 즉시 표시되고 검색 엔진 최적화(SEO)에 매우 유리합니다 [37-40]. 그러나 브라우저가 JavaScript를 다운로드하고 이벤트 리스너를 연결하는 Hydration 과정이 끝날 때까지는 페이지와 상호작용할 수 없는(TTI 지연) 단점이 있습니다 [37, 41-43].
* **SSG (Static Site Generation):** 빌드 시점에 정적 HTML을 생성하고 CDN을 통해 즉각적으로 제공하는 방식입니다 [44-46]. 속도가 가장 빠르고 SEO가 뛰어나지만, 실시간 데이터가 필요한 동적 콘텐츠 페이지에는 적합하지 않습니다 [44, 47-49].
* **컴포넌트 기반 아키텍처 (CBA) 개념:**
애플리케이션을 독립적이고 재사용 가능하며 캡슐화된 구성 요소(컴포넌트)로 나누어 조립하는 소프트웨어 설계 방식입니다 [50-53]. 각 컴포넌트는 자체적인 데이터와 UI 로직을 포함하며, 잘 정의된 인터페이스(API)를 통해서만 상호작용합니다 [50, 51, 54]. 이 아키텍처는 코드의 재사용성을 높여 개발 속도를 단축하고, 각 팀이 병렬로 작업할 수 있도록 모듈성을 제공하며, 특정 컴포넌트만 수정 및 교체할 수 있어 시스템의 유지보수성과 확장성을 극대화합니다 [55-59].
## 🔗 Knowledge Connections
- **Related Topics:** [[중요 렌더링 경로 (Critical Rendering Path)]], [[가상 DOM과 재조정 (Reconciliation)]], [[Hydration 성능 최적화]], [[Fiber 아키텍처와 동시성 (Concurrent Rendering)]], [[단일 페이지 애플리케이션 (SPA)]]
- **Projects/Contexts:** [[웹 프론트엔드 아키텍처 설계]], [[성능 및 SEO 최적화 프로젝트]]
- **Contradictions/Notes:** 소스에 따르면 SSR은 서버에서 완전히 렌더링된 HTML을 제공하여 첫 화면 표시(FCP) 속도를 획기적으로 개선하지만, JavaScript 번들을 다운로드하고 하이드레이션(Hydration)이 완료되기 전까지는 사용자가 상호작용할 수 없기 때문에 TTI(Time to Interactive)는 오히려 지연될 수 있습니다. 이는 초기 콘텐츠 렌더링과 상호작용 활성화 사이의 성능 트레이드오프(Trade-off)를 의미합니다 [37, 42, 43, 60].
---
*Last updated: 2026-04-25*