feat: Knowledge Gardening Milestone 420 (Batch #21)

This commit is contained in:
Antigravity Agent
2026-04-26 20:05:02 +09:00
parent 4197d97b0a
commit 35d868b28d
27 changed files with 839 additions and 0 deletions
@@ -0,0 +1,105 @@
# Skybound Hangar Layout Guardrails Scroll Islands
작성일: 2026-04-26 17:24 KST
## 요청 요약
- Mount Bays 목록이 전체적으로 확인되지 않고 하단이 잘린다.
- 이런 문제가 여러 UI에서 반복적으로 발생한다.
- 사용자가 하나씩 찾아서 수정 요청하기 어렵기 때문에 근본적으로 수정해야 한다.
## 핵심 문제
행거 UI에는 `overflow: hidden`과 고정 높이 카드가 여러 곳에 섞여 있었다.
특히 Loadout 화면의 Mount Bays는 다음 구조였다.
- 부모 컬럼은 `overflow: hidden`
- 내부 슬롯은 고정 `min-height`
- 화면 높이가 줄어들면 마지막 슬롯이 부모 밖으로 밀림
- 부모가 hidden이므로 사용자가 확인하거나 스크롤할 수 없음
이 문제는 Mount Bays만의 문제가 아니라, 장비 목록, 업그레이드 목록, 포지 목록처럼 콘텐츠량이 가변적인 UI 전반에서 반복될 수 있는 구조적 문제다.
## 적용한 해결 방향
이번 수정은 개별 카드 하나를 줄이는 방식이 아니라, 행거 전체에 `Scroll Island` 규칙을 추가하는 방향으로 처리했다.
원칙:
- 화면 전체는 가능한 한 유지한다.
- 콘텐츠가 많은 영역만 내부 스크롤을 가진다.
- `overflow: hidden`은 레이아웃 컨테이너를 안정화하는 곳에만 쓰고, 실제 목록 영역은 반드시 스크롤 가능하게 둔다.
- 고정 높이보다 `minmax(0, 1fr)``min-height: 0`을 우선한다.
- 작은 화면에서는 외부 shell 자체도 스크롤 가능하게 둔다.
## 적용한 변경
### 행거 전체 레이아웃 방어선 추가
변경:
- `.hangar-overlay``overflow: auto`로 변경
- `.hangar-inner``96vh` 기준으로 확장
- grid row를 `auto minmax(0, 1fr) auto`로 고정
- 주요 패널에 `min-height: 0` 적용
의도:
- 전체 화면 높이가 줄어도 UI가 잘려 접근 불가능해지는 상황을 방지한다.
### 탭 콘텐츠 공통 스크롤 처리
변경:
- `.tab-content`, `.upgrade-shop`, `.pass-panel`에 내부 스크롤 규칙 적용
- 공통 스크롤바 스타일 적용
- 목록형 영역에 `overscroll-behavior: contain` 적용
의도:
- 특정 탭의 콘텐츠가 많아도 화면 밖으로 사라지지 않고 해당 탭 내부에서 스크롤된다.
### Mount Bays 스크롤 아일랜드 적용
변경:
- `.mount-bay-column`을 grid로 변경
- 제목 영역과 목록 영역을 분리
- `.slots-container.compact``overflow-y: auto` 적용
- 슬롯 최소 높이를 줄여 4개 부위가 더 안정적으로 보이도록 조정
의도:
- Weapon, Armor, Engine, Wings를 모두 접근 가능하게 한다.
- 화면 높이가 작아져도 마지막 Aero Stabilizer가 숨지 않게 한다.
### Footer 압축 및 작은 화면 대응
변경:
- Footer 최소 높이 축소
- Mission Mode, Tactical Support, Launch 영역이 메인 콘텐츠를 과도하게 밀어내지 않도록 조정
- 낮은 화면 높이에서는 카드 높이와 미리보기 높이를 자동으로 압축
- 좁은 화면에서는 left telemetry panel을 숨기고 메인 콘텐츠 우선
의도:
- 핵심 작업 영역이 footer 때문에 잘리는 문제를 줄인다.
## 수정 파일
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/HangarOverlay.css`
## 검증
- `npm run build` 성공
- 출력 디렉터리: `dist/43`
## 후속 체크 포인트
- Loadout에서 Mount Bays 4개가 모두 접근 가능한지 확인한다.
- 화면 높이를 줄였을 때 Mount Bays 내부 스크롤이 동작하는지 확인한다.
- Upgrade, Merge, Salvage, Forge, Pass 탭에서 목록이 잘리지 않는지 확인한다.
- Footer가 메인 콘텐츠를 과하게 밀어내지 않는지 확인한다.
- 좁은 화면에서 left telemetry panel이 숨겨져도 핵심 기능 접근이 가능한지 확인한다.
+29
View File
@@ -0,0 +1,29 @@
# [[Code Splitting and Lazy Loading]]
## 📌 Brief Summary
**Code Splitting(코드 분할)**과 **Lazy Loading(지연 로딩)**은 방대한 자바스크립트 번들을 더 작은 청크(chunk) 단위로 나누고, 사용자가 필요로 하는 시점에만 온디맨드(on-demand) 방식으로 코드를 로드하는 프런트엔드 최적화 기법입니다[1-3]. 이 기법을 사용하면 초기 다운로드해야 하는 번들 크기를 크게 줄여 페이지 로드 시간과 사용자 인지 성능을 획기적으로 향상시킬 수 있습니다[1, 4]. React 환경에서는 주로 동적 임포트와 결합된 `React.lazy()``<Suspense>`를 활용해 구현됩니다[5, 6].
## 📖 Core Content
* **초기 번들 크기 문제와 해결책:**
기본적으로 모던 프런트엔드 애플리케이션은 모든 앱 코드와 외부 종속성(dependencies)을 하나의 거대한 자바스크립트 파일(번들)로 패키징합니다. 이는 긴 다운로드 시간, 무거운 파싱 및 컴파일 작업, 그리고 Core Web Vitals(FCP, LCP, INP) 지표의 하락을 유발합니다[3, 7]. **코드 스플리팅**은 이 거대한 번들을 분할하여, 애플리케이션 초기 구동에 불필요한 코드를 분리함으로써 이러한 성능 병목 현상을 해결합니다[3, 8].
* **스플리팅 및 지연 로딩의 적용 전략:**
* **라우트 기반 스플리팅(Route-level splitting):** 사용자가 특정 페이지 경로(Route)로 네비게이션할 때만 해당 화면의 코드를 다운로드하게 하여 초기 로드 속도를 획기적으로 향상시키는 가장 일반적인 접근 방식입니다[2, 3, 9].
* **컴포넌트 수준 지연 로딩(Component-level lazy loading):** 차트, 지도, 리치 텍스트 에디터처럼 무겁거나, 모달 창 및 관리자 설정 패널처럼 사용 빈도가 낮은 UI 블록을 렌더링이 필요한 순간에만 로드합니다[5, 10].
* **React에서의 구현 방법 (`React.lazy``Suspense`):**
React는 내장 함수인 `React.lazy()`를 제공하여 컴포넌트를 동적으로 임포트(`import()`)할 수 있도록 지원합니다[1, 5]. 이때 분할된 코드가 다운로드되는 동안 화면에 보여줄 로딩 스피너나 스켈레톤 UI와 같은 폴백(fallback) 화면은 `<Suspense>` 컴포넌트를 통해 정의합니다[6, 9]. 이러한 방식을 적용하면 앱 복잡도에 따라 초기 번들 크기를 최대 20~70%까지 줄일 수 있습니다[6].
* **이미지 지연 로딩 최적화:**
자바스크립트뿐만 아니라 이미지 역시 페이지 용량의 큰 부분을 차지합니다. 스크롤 아래에 위치해 당장 보이지 않는 이미지의 경우, 자바스크립트를 복잡하게 구현할 필요 없이 브라우저 네이티브 속성인 `loading="lazy"`를 사용하여 불필요한 리소스 다운로드를 방지할 수 있습니다[11].
* **적용 시 주의사항 (안티 패턴):**
지연 로딩은 강력하지만, 화면 최상단에 있어 스크롤 없이 즉시 보여야 하는 필수 영역(above-the-fold) 컴포넌트나, 렌더링 속도가 매우 빨라 즉각적으로 표시되어야 하는 요소들에는 적용을 피해야 합니다[10, 11]. 이들에 적용하면 오히려 사용자 경험(UX)을 지연시킬 수 있습니다.
## 🔗 Knowledge Connections
- **Related Topics:** [[React Performance Optimization]], [[Core Web Vitals]], [[Suspense]]
- **Projects/Contexts:** [[Vite]], [[Next.js]]
- **Contradictions/Notes:** 지연 로딩은 초기 로딩 속도 향상을 위한 핵심 도구이지만, 화면 첫 렌더링에 핵심적인 부분(above-the-fold 요소 등)에 남용하면 반대로 렌더링 지연을 초래하므로 주의 깊게 측정하고 분리해야 합니다[10, 11].
---
*Last updated: 2026-04-26*
@@ -0,0 +1,24 @@
# [[Frontend App Development Architecture]]
## 📌 Brief Summary
프론트엔드 앱 개발 아키텍처는 확장성, 유지보수성, 성능을 고려하여 프론트엔드 시스템을 설계하고 구성하는 기반 프레임워크입니다 [1, 2]. 과거의 단순한 기술적 파일 기반 분리에서 벗어나, 비즈니스 로직과 기능(Feature)을 중심으로 모듈화하고 결합도를 낮추는 방향으로 아키텍처 패러다임이 전환되었습니다 [3, 4]. 일관된 폴더 구조, 상태 관리 패러다임, 클린 코드 원칙을 적용함으로써 애플리케이션이 복잡해지더라도 안정적으로 확장할 수 있도록 돕습니다 [5, 6].
## 📖 Core Content
* **모듈화와 폴더 구조 (Folder Structure):**
과거에는 컴포넌트, 훅, 스타일 등 파일 유형(Type)별로 코드를 나누는 방식을 사용했으나, 이는 애플리케이션이 커질수록 확장성이 떨어집니다 [3, 7]. 현대 프론트엔드 아키텍처는 도메인이나 기능별로 코드를 캡슐화하는 기능 기반(Feature-based) 구조를 채택합니다 [4, 8, 9]. 특히 **Feature-Sliced Design (FSD)**은 프론트엔드 아키텍처에 특화된 방법론으로, 코드를 레이어(app, pages, widgets, features, entities, shared)로 나누고 상위 레이어에서 하위 레이어로만 의존성을 가지도록 강제하여 순환 참조를 방지하고 아키텍처 규율을 유지합니다 [10-13].
* **소프트웨어 공학 원칙 (SOLID & Clean Code):**
React 컴포넌트에도 객체지향 설계의 SOLID 원칙이 적용됩니다. 컴포넌트는 단일 책임(SRP)을 가져야 하며 300줄 이상 길어지면 분리를 고려해야 하고, Composition을 통해 확장에는 열려 있고 수정에는 닫혀 있도록(OCP) 설계해야 합니다 [14-16]. 또한 DRY(반복하지 마라), KISS(단순하게 유지하라), YAGNI(필요할 때만 구현하라) 원칙을 통해 과도한 추상화를 피하고, 현재 요구사항에 집중해 예측 가능하고 디버깅하기 쉬운 코드를 작성해야 합니다 [17-19].
* **상태 관리의 파편화 (State Management):**
모든 상태를 거대한 단일 스토어(예: Redux)에 넣는 방식에서 벗어나, 목적에 맞는 도구로 분리하는 것이 2025년의 트렌드입니다 [20]. API에서 가져온 '서버 상태'는 캐싱과 동기화를 지원하는 TanStack Query(React Query)로 관리하며, '전역 애플리케이션 상태'는 리렌더링 최적화가 뛰어난 Zustand 같은 가벼운 라이브러리를 사용합니다 [20-22].
* **명명 규칙과 거버넌스 (Naming Conventions & Governance):**
대소문자 구분이 없는 OS(Windows, macOS) 환경에서 발생할 수 있는 CI/CD 빌드 오류를 방지하기 위해 파일과 폴더 이름은 `kebab-case`를 사용합니다 [23, 24]. 반면 React 컴포넌트는 `PascalCase`를, 일반 변수와 커스텀 훅은 `camelCase`를 사용하는 것이 업계 표준입니다 [23, 25-27]. 자동화된 거버넌스를 위해 ESLint, Prettier, Husky를 도입하여 커밋 전에 린팅과 포매팅을 강제하는 것이 좋습니다 [25].
* **성능 최적화 및 안정성 (Performance & Reliability):**
Vite와 같은 현대적인 번들러를 사용하여 서드파티 라이브러리를 분리(manualChunks)하고, `React.lazy`와 동적 임포트를 통한 코드 스플리팅을 적용하면 초기 번들 크기와 로딩 시간을 획기적으로 줄일 수 있습니다 [28-32]. 런타임 오류 시 애플리케이션 전체가 멈추는 백화현상을 막기 위해 'React Error Boundaries'를 도입해 실패를 국소화하고 대체 UI를 렌더링해야 합니다 [33-35]. 최근 안정화된 React Compiler는 `useMemo``useCallback`과 같은 수동 메모이제이션을 자동화해 주어 클린 코드를 유지하면서 불필요한 렌더링을 방지해 줍니다 [36-39].
## 🔗 Knowledge Connections
- **Related Topics:** [[Feature-Sliced Design]], [[SOLID Principles]], [[State Management]], [[React Error Boundaries]], [[React Compiler]]
- **Projects/Contexts:** [[React Project Structure]], [[Performance Optimization]], [[Frontend Refactoring]]
- **Contradictions/Notes:** Context API는 별도의 외부 종속성 없이 상태를 공유할 수 있는 React 내장 도구이지만, 하나의 값이 변경될 때 구독 중인 모든 컴포넌트를 리렌더링하는 문제(Re-render storm)가 있습니다 [40, 41]. 따라서 잦은 업데이트가 필요한 상태에는 부적합하며, 이 경우 Zustand 등의 툴이 권장됩니다 [22, 42]. 또한 DRY(반복 지양) 원칙은 유용하지만, 코드를 너무 과도하게 추상화하면 직관성을 해쳐 오히려 KISS(단순성 유지) 원칙에 위배될 수 있으므로, 동일 패턴이 세 번 이상 반복될 때만 추상화하는 것이 이상적입니다 [17, 18, 43]. Atomic Design 모델은 UI 컴포넌트의 재사용성을 높이는 데에는 훌륭하지만 비즈니스 로직과 상태를 구조화하는 데는 부족하므로, 대규모 앱에서는 FSD 방법론이 더욱 유용합니다 [44-46].
---
*Last updated: 2026-04-26*
+28
View File
@@ -0,0 +1,28 @@
# [[Git Branching Strategies]]
## 📌 Brief Summary
Git 브랜칭 전략은 소프트웨어 개발 팀이 코드 변경 사항을 효율적으로 관리하고 통합하기 위해 사용하는 체계적인 워크플로우입니다. 이 전략은 메인(main) 코드베이스의 안정성을 보호하면서 기능 개발, 버그 수정 등을 격리된 환경(브랜치)에서 수행할 수 있도록 돕습니다 [1-3]. 팀의 규모와 프로젝트 요구사항에 따라 Feature Branch Workflow, Trunk-Based Development, Git Flow 등 다양한 전략을 맞춤 적용하여 코드 충돌을 방지하고 협업 효율을 극대화할 수 있습니다 [3, 4].
## 📖 Core Content
* **주요 브랜칭 전략**
* **Feature Branch Workflow (기능 브랜치 워크플로우)**: 2~5명 규모의 소규모 팀에게 가장 초보자 친화적이고 권장되는 방식입니다 [2, 4]. 메인(main) 브랜치는 항상 안정적이고 배포 가능한 상태로 유지하며, 새로운 작업이 필요할 때마다 메인에서 분기된 짧은 수명의 기능 브랜치를 생성하여 작업합니다 [1, 2, 5].
* **Trunk-Based Development (트렁크 기반 개발)**: 강력한 CI/CD 환경을 갖춘 숙련된 팀에 적합하며, 짧은 수명의 기능 브랜치를 통해 작고 잦은 커밋을 메인에 병합하는 방식입니다 [1, 4].
* **Git Flow & GitHub Flow**: Git Flow는 정기적인 릴리스가 필요한 대규모 프로젝트에 적합하지만 소규모 팀이 사용하기에는 너무 무거울 수 있습니다 [4]. 반면 GitHub Flow는 메인 브랜치로 직접 병합하여 배포를 단순화하는 유연한 전략입니다 [6, 7].
* **핵심 규칙 및 모범 사례 (Best Practices)**
* **브랜치 명명 규칙**: 브랜치 이름은 서술적이고 짧게 유지해야 합니다(예: `feature/user-auth`, `bugfix/login-error`) [8-10]. 이슈 트래커의 티켓 ID(예: `PROJ-123`)를 포함하면 코드 변경 사항과 비즈니스 요구사항 간의 추적성을 크게 높일 수 있습니다 [11, 12].
* **커밋 규칙 (Conventional Commits)**: 커밋은 의미 있는 작은 단위로 자주 수행해야 합니다 [9, 13]. `feat`(새 기능), `fix`(버그 수정), `docs`(문서), `refactor`(리팩토링), `chore`(유지보수) 등의 일관된 접두사를 사용하여 커밋의 목적을 명확히 하는 것이 좋습니다 [14-16].
* **Pull Request (PR) 및 병합**: 작업이 완료되면 반드시 PR을 생성하여 최소 1명 이상의 동료 리뷰와 CI/CD 테스트 통과를 거친 후 병합해야 합니다 [11, 13, 17]. 깔끔한 커밋 히스토리를 유지하기 위해 'Squash Merge(스쿼시 병합)'를 사용하는 것이 좋으며, 병합이 완료된 기능 브랜치는 즉시 삭제하여 저장소를 정리해야 합니다 [11, 13, 18].
* **피해야 할 안티 패턴 (Anti-Patterns)**
* 보호되어야 할 메인(main) 브랜치에 직접 코드를 커밋하는 행위 [19, 20].
* 수명이 너무 긴 기능 브랜치를 방치하여 거대한 병합 충돌(Merge Conflict)을 유발하는 행위 [21, 22].
* 코드 리뷰를 건너뛰거나, CI 테스트를 통과하지 못한 깨진 코드를 병합하는 행위 [20, 22].
## 🔗 Knowledge Connections
- **Related Topics:** [[Conventional Commits]], [[Pull Request Workflow]], [[CI/CD Pipeline]]
- **Projects/Contexts:** [[Frontend Team Collaboration]], [[Small Team Development]]
- **Contradictions/Notes:** 대규모 프로젝트에 자주 쓰이는 'Git Flow' 전략은 2~5명 규모의 소규모 팀에게는 프로세스 오버헤드가 커서 부적합하며, 대신 더 가벼운 'Feature Branch Workflow'나 'Trunk-Based Development'를 사용하는 것이 실무적으로 훨씬 권장됩니다 [1, 4, 23].
---
*Last updated: 2026-04-26*
+30
View File
@@ -0,0 +1,30 @@
# [[Memory Leak Debugging]]
## 📌 Brief Summary
메모리 누수는 애플리케이션이 메모리를 할당한 후 더 이상 필요하지 않음에도 불구하고 이를 해제(release)하지 않아 메모리 소비가 지속적으로 증가하는 현상을 의미합니다 [1]. 이러한 문제는 시간이 지남에 따라 애플리케이션의 성능을 점진적으로 저하시키고, 인터페이스를 느리게 만들며, 궁극적으로 브라우저 탭의 멈춤이나 충돌을 유발합니다 [2-4]. 프론트엔드 환경에서 메모리 누수를 해결하려면 Chrome DevTools와 같은 도구를 활용하여 메모리 할당을 프로파일링하고, 분리된 DOM 노드나 정리되지 않은 이벤트 리스너 등의 원인을 찾아 수정해야 합니다 [5-7].
## 📖 Core Content
* **메모리 누수의 정의와 주요 증상**
자바스크립트에서 가비지 컬렉터(Garbage Collector)는 사용되지 않는 메모리를 자동으로 회수하지만, 변수 등에 참조가 남아있을 경우 메모리가 해제되지 않고 누수됩니다 [1]. 이러한 메모리 누수는 작업 부하가 일정함에도 불구하고 메모리 사용량이 감소하지 않고 꾸준히 증가하는 특징을 보입니다 [4]. 주요 증상으로는 장시간 사용 후 성능 저하, 잦은 화면 멈춤, 특히 모바일 기기에서의 잦은 앱 충돌 등이 있습니다 [2-4].
* **프론트엔드의 주요 메모리 누수 패턴**
* **분리된 DOM 노드 (Detached DOM Nodes):** DOM 트리에서는 제거되었지만 자바스크립트 코드나 변수에서 여전히 참조를 유지하고 있어 가비지 컬렉션의 대상이 되지 못하는 노드입니다 [8, 9].
* **이벤트 리스너 누적 (Event Listener Accumulation):** React의 `useEffect` 등에서 컴포넌트가 언마운트될 때 등록된 이벤트 리스너나 구독을 정리(cleanup) 해주는 함수를 반환하지 않으면 발생합니다 [9-12].
* **클로저에 의해 유지되는 참조 (Closure-Retained References):** 클로저가 부모 스코프의 변수를 계속 살려두어 불필요하게 큰 객체를 메모리에 남겨두는 경우입니다 [13].
* **디버깅 및 탐지 방법**
* **Chrome 작업 관리자:** 실시간으로 모니터링하며 'JavaScript Memory' 항목의 괄호 안 숫자(라이브 숫자)가 꾸준히 증가하는지 확인하여 누수의 1차적 징후를 발견할 수 있습니다 [14, 15].
* **성능 패널 (Performance Panel):** 시간 경과에 따른 메모리 사용량을 시각화하며, 강제 가비지 컬렉션 이후에도 JS 힙(Heap) 크기가 이전보다 높은 상태로 종료된다면 메모리 누수를 의심해야 합니다 [16, 17].
* **힙 스냅샷 (Heap Snapshots):** 메모리 상태의 스냅샷을 캡처한 뒤 'Detached' 키워드로 검색하여 분리된 DOM 트리를 찾거나, 작업 전후의 두 스냅샷을 비교(Comparison)하여 지속적으로 델타(Delta) 크기가 증가하는 객체를 식별할 수 있습니다 [6, 9, 11, 18].
* **할당 타임라인 (Allocation Timelines):** 메모리 할당 패턴을 실시간으로 추적하여, 회색으로 변하지 않고 남아있는 파란색 막대(해제되지 않은 메모리 할당)를 통해 특정 사용자 상호작용 중 발생하는 누수를 찾아냅니다 [19-21].
* **예방 및 모범 사례**
대규모 객체 캐싱에는 가비지 컬렉션을 방해하지 않는 `WeakMap`을 사용하는 것이 권장됩니다 [12]. React 애플리케이션에서는 컴포넌트의 수명 주기에 맞춰 `useEffect` 내에서 항상 이벤트 리스너를 제거하거나 구독을 취소하는 정리(cleanup) 함수를 제공하여 메모리 누수를 미연에 방지해야 합니다 [10-12].
## 🔗 Knowledge Connections
- **Related Topics:** [[React Hooks]], [[Performance Optimization]], [[Garbage Collection]]
- **Projects/Contexts:** [[Frontend Application Debugging]], [[Scalable React Architecture]]
- **Contradictions/Notes:** 소스의 메모리 누수 디버깅 기법들은 주로 Chrome DevTools를 기준으로 설명되며, React 개발자는 Hook의 생명주기를 정확히 이해하여 cleanup을 수행하는 것이 메모리 최적화에 직결됨을 강조합니다 [5, 11, 22].
---
*Last updated: 2026-04-26*
+22
View File
@@ -0,0 +1,22 @@
# [[React Error Boundaries]]
## 📌 Brief Summary
React Error Boundaries는 하위 컴포넌트 트리의 렌더링, 수명 주기 메서드 또는 생성자에서 발생하는 JavaScript 에러를 포착하는 특수한 클래스 컴포넌트입니다 [1, 2]. 이 메커니즘은 앱 전체가 다운되거나 빈 화면(white screen of death)이 표시되는 것을 방지하고 대신 대체 UI(fallback UI)를 표시하도록 돕습니다 [1, 2]. 본질적으로 React 컴포넌트를 위한 `try-catch` 블록처럼 작동하여 프론트엔드 애플리케이션의 안정성과 사용자 경험을 높여줍니다 [2, 3].
## 📖 Core Content
* **작동 원리 및 제약 사항:**
Error Boundaries는 클래스 컴포넌트로만 생성할 수 있으며, 오류 발생 후 대체 UI를 렌더링하기 위한 `static getDerivedStateFromError()`나 오류 정보를 기록하기 위한 `componentDidCatch()` 생명주기 메서드 중 하나 이상을 정의해야 작동합니다 [3-5]. 단, 이벤트 핸들러, 비동기 코드(예: `setTimeout`), 서버 사이드 렌더링(SSR), 혹은 Error Boundary 자체에서 발생한 에러는 포착하지 못합니다 [4, 5]. 이벤트 핸들러의 경우 표준 JavaScript의 `try/catch` 문을 직접 사용해야 합니다 [5-7].
* **전략적 배치 및 모범 사례:**
애플리케이션 전체를 단일 Error Boundary로 감싸기보다는, 불안정하거나 중요한 UI 섹션(예: 타사 위젯, 차트, 복잡한 폼 등)을 개별적으로 감싸는 것이 권장됩니다 [8-10]. 예를 들어, 사이드바나 메시지 입력창 중 한 곳이 충돌하더라도 개별적인 Error Boundary가 설정되어 있다면 나머지 UI 부분은 계속 상호작용 가능한 상태로 유지될 수 있습니다 [8, 11].
* **프로덕션 환경 적용 및 복구성 향상:**
프로덕션 환경에서는 Error Boundaries를 Sentry나 LogRocket과 같은 로깅 및 모니터링 도구와 통합하여 에러 세부 정보를 캡처하는 것이 모범 사례로 꼽힙니다 [10]. React 16부터는 Error Boundary에 의해 포착되지 않은 에러는 전체 React 컴포넌트 트리의 마운트 해제(unmounting)를 초래하여 심각한 문제를 일으킬 수 있으므로, 적절한 에러 경계 설정은 확장 가능하고 견고한 애플리케이션을 유지하는 데 필수적입니다 [9, 12].
## 🔗 Knowledge Connections
- **Related Topics:** [[Class Components]], [[Fallback UI]], [[Frontend Debugging]], [[Component Lifecycle]]
- **Projects/Contexts:** [[Sentry/LogRocket Monitoring]], [[Scalable React Architecture]], [[Error Handling in 2025]]
- **Contradictions/Notes:** Error Boundaries는 렌더링 오류를 잡기 위해 설계된 훌륭한 기능이지만, 함수형 컴포넌트로는 직접 만들 수 없으며 컴포넌트의 이벤트 핸들러 내의 오류는 포착하지 못하므로 이벤트 핸들러는 일반적인 `try/catch`로 별도 처리해야 합니다 [3, 5, 6].
---
*Last updated: 2026-04-26*
+33
View File
@@ -0,0 +1,33 @@
# [[React State Management]]
## 📌 Brief Summary
React 상태 관리(State Management)는 애플리케이션의 데이터 흐름과 UI 업데이트를 제어하는 핵심 메커니즘이다. 과거의 단일 스토어 방식에서 벗어나, 최근에는 상태의 성격(로컬, 전역, 서버 캐시 등)에 따라 가장 적합한 도구를 결합하여 사용하는 파편화(Fragmentation) 접근법이 표준으로 자리 잡았다 [1, 2]. 개발자는 앱의 규모, 팀의 크기, 상태 변경의 빈도에 맞춰 Context API, Zustand, Redux, TanStack Query 등을 전략적으로 선택하여 확장성을 높이고 성능 저하를 방지해야 한다 [1, 3].
## 📖 Core 소스 Content
* **상태의 분류와 파편화 (Fragmentation of State)**
* 현재 프론트엔드 아키텍처에서는 상태를 로컬 컴포넌트 상태, 전역 애플리케이션 상태, 서버 캐시 상태, URL 상태로 명확히 구분한다 [1].
* **로컬 상태:** React 내장 훅인 `useState``useReducer`를 주로 사용하지만, 지나치게 복잡한 상태를 `useState`로만 관리하려는 잘못된 패턴은 피해야 한다 [1, 4].
* **서버 상태:** API 계층에서 가져온 데이터는 클라이언트 상태와 근본적으로 다르므로 캐싱, 동기화, 로딩 및 에러 처리가 필요하다 [2]. 이를 위해 TanStack Query(React Query)와 같은 라이브러리가 업계 표준으로 사용되며, 중복 네트워크 요청을 줄이고 무한 스크롤 등을 단순화한다 [2, 5]. RTK Query 또한 캐싱, 중복 제거, 자동 리패칭 등을 제공해 비동기 작업의 복잡성을 크게 줄여준다 [6].
* **Context API의 한계와 적합성**
* **적합한 사례:** 종속성 추가 없이(Zero dependencies) 테마 변경(다크/라이트 모드), 다국어 설정, 피처 플래그 등 변경이 드물고 정적인 전역 상태를 관리하는 데 적합하다 [7, 8].
* **한계:** 특정 값이 변경될 때마다 Context를 구독하는 모든 컴포넌트가 불필요하게 리렌더링되는 성능 문제(Re-render storm)를 유발한다 [9, 10]. 또한, Redux와 달리 상태 변경 기록을 추적하는 Time-Travel 디버깅 도구를 지원하지 않는다 [11].
* **Zustand를 활용한 최적화**
* **작동 방식:** Context API의 리렌더링 문제를 해결하기 위해 도입된 경량 상태 관리 라이브러리다. 스토어가 React의 컴포넌트 트리 외부에 위치하며, '선택자(Selector pattern)'를 사용해 컴포넌트가 의존하는 특정 상태(Slice)가 변경될 때만 리렌더링을 트리거한다 [2, 12, 13].
* **장단점:** 설정이 단순하고 속도가 빨라 5~15명 규모의 팀과 중간 규모 애플리케이션에 매우 적합하다 [14]. 단, 구조가 너무 유연하여 엄격한 규율이 없을 경우 팀원마다 비동기 호출이나 상태 관리 패턴이 일관성 없이 파편화될 위험이 있다 [15, 16].
* **Redux (Redux Toolkit)와 대규모 애플리케이션**
* Redux는 불변성 업데이트와 액션 디스패치, 리듀서를 통해 일관되고 예측 가능한 상태 컨테이너를 제공하는 산업 표준이다 [17].
* 복잡한 파생 상태 관리가 필요하고 500개 이상의 컴포넌트를 다루거나, 10명 이상의 개발자가 협업하는 대규모 미션 크리티컬 애플리케이션에 적합하다 [18]. 강력한 구조를 강제하여 버그를 사전에 방지하며, Redux DevTools를 통해 복잡한 비동기 상태 에러를 빠르게 추적하고 디버깅할 수 있다 [19, 20].
* **아키텍처 관점에서의 상태 위치 (Feature-Sliced Design)**
* Feature-Sliced Design (FSD) 아키텍처에서는 상태 관리 라이브러리의 종류와 무관하게 상태의 소유권을 명확히 제한한다. 엔티티 상태는 `entities` 레이어에, 특정 유저 시나리오의 상태는 `features` 레이어에, 글로벌 인프라 상태는 `app` 레이어에 두어 결합도를 낮춰야 한다 [21, 22].
## 🔗 Knowledge Connections
- **Related Topics:** [[Frontend Performance Optimization]], [[Feature-Sliced Design]], [[React Hooks]], [[Clean Code Principles]]
- **Projects/Contexts:** [[Redux Toolkit]], [[Zustand]], [[TanStack Query]], [[React Context API]]
- **Contradictions/Notes:** 상태 관리 라이브러리를 선택할 때 단순히 번들 크기(Context 0KB, Zustand 2.2KB, Redux 4.3KB)만을 비교하는 것은 잘못된 접근이라고 지적된다. 번들 크기가 작더라도 Context API를 잘못 사용할 경우 디버깅과 리렌더링 최적화에 막대한 개발 시간이 낭비될 수 있으므로, 팀 규모와 기능의 복잡성을 기준으로 선택해야 한다 [7, 9, 23].
---
*Last updated: 2026-04-26*