feat: Wiki-fication of 00_Raw data (Batch #5 - Component Composition, CWV, Hooks, Context, UX)
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# Skybound Runtime Asset Path Legacy Background Airframe Fix
|
||||
|
||||
작성일: 2026-04-26 17:52 KST
|
||||
|
||||
## 요청 요약
|
||||
|
||||
- 게임 배경이 새로 만든 배경이 아니라 레거시 배경처럼 보인다.
|
||||
- 사용자 비행기도 기존 레거시 비행기처럼 보인다.
|
||||
- 뭔가 잘못된 경로 또는 에셋 연결 문제가 있는지 확인해야 한다.
|
||||
|
||||
## 확인 결과
|
||||
|
||||
사용자 지적이 맞았다.
|
||||
|
||||
전투 런타임의 핵심 에셋 로더가 아직 아래 레거시 파일을 직접 읽고 있었다.
|
||||
|
||||
- `/sprites/Falcon.png`
|
||||
- `/sprites/rayce.png`
|
||||
- `/sprites/background/stage_tile_1.png` ~ `/sprites/background/stage_tile_8.png`
|
||||
|
||||
즉 UI, HUD, 밸런스, 전투 연출은 새 톤앤매너로 계속 개선되고 있었지만, 실제 캔버스 렌더러의 핵심 배경/기체 스프라이트 경로는 예전 파일을 보고 있었다.
|
||||
|
||||
## 핵심 문제
|
||||
|
||||
레거시 PNG가 아직 `public/sprites`에 남아 있는 것 자체는 문제가 아니다.
|
||||
|
||||
문제는 런타임 로더가 새 아트 전용 경로를 참조하지 않고, 기존 파일명을 직접 참조하고 있었다는 점이다.
|
||||
|
||||
이 때문에:
|
||||
|
||||
- 전투 배경이 예전 rounded grid tile처럼 보였다.
|
||||
- 사용자 기체가 새 톤의 마기테크 기체가 아니라 기존 프로토타입 기체처럼 보였다.
|
||||
- 선택 화면/프리뷰 일부에서도 레거시 기체 이미지가 다시 노출될 가능성이 있었다.
|
||||
|
||||
## 적용한 해결 방향
|
||||
|
||||
레거시 파일을 덮어쓰지 않고, 새 전용 에셋 경로를 만들었다.
|
||||
|
||||
이유:
|
||||
|
||||
- 기존 파일을 덮어쓰면 다른 코드나 문서에서 원본 비교가 어려워진다.
|
||||
- 새 경로를 명시하면 이후에도 “어떤 파일이 현재 톤앤매너 기준 에셋인지”가 분명해진다.
|
||||
- 런타임에서 레거시 파일이 다시 끼어드는 문제를 검색으로 확인하기 쉬워진다.
|
||||
|
||||
## 적용한 변경
|
||||
|
||||
### 새 사용자 기체 에셋 추가
|
||||
|
||||
추가 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/player/falcon_magitech.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/player/rayce_magitech.svg`
|
||||
|
||||
방향:
|
||||
|
||||
- 투명 배경
|
||||
- bold outline
|
||||
- flat lighting
|
||||
- cyan/lime/orange magical accent
|
||||
- 캔버스에서 78px 정도로 축소되어도 읽히는 큰 실루엣
|
||||
|
||||
### 새 스테이지 배경 에셋 추가
|
||||
|
||||
추가 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_1.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_2.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_3.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_4.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_5.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_6.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_7.svg`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/public/sprites/background/stylized_magitech_stage_8.svg`
|
||||
|
||||
방향:
|
||||
|
||||
- 기존 rounded square grid 느낌 제거
|
||||
- 어두운 magitech plate 구조
|
||||
- 낮은 대비의 배경 판독성
|
||||
- cyan/lime/orange/red stage accent
|
||||
- 적과 탄환보다 과하게 튀지 않도록 배경 채도 억제
|
||||
|
||||
### 런타임 에셋 로더 교체
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/hooks/useGameAssets.ts`
|
||||
|
||||
변경:
|
||||
|
||||
- `player_falcon` 로딩 경로를 `/sprites/player/falcon_magitech.svg`로 변경
|
||||
- `player_rayce` 로딩 경로를 `/sprites/player/rayce_magitech.svg`로 변경
|
||||
- 스테이지 배경 로딩 경로를 `/sprites/background/stylized_magitech_stage_*.svg`로 변경
|
||||
|
||||
### 선택/프리뷰 잔여 레거시 경로 제거
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/src/App.css`
|
||||
- `/Volumes/Data/project/Antigravity/Skybound/src/features/game/ui/SelectCard.tsx`
|
||||
|
||||
변경:
|
||||
|
||||
- 선택 카드/프리뷰에서 `/sprites/Falcon.png`, `/sprites/rayce.png`를 직접 참조하던 경로를 새 SVG 경로로 변경했다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `npm run build` 성공
|
||||
- 출력 디렉터리: `dist/46`
|
||||
- `src` 기준 레거시 직접 참조 검색 결과:
|
||||
- `Falcon.png` 없음
|
||||
- `rayce.png` 없음
|
||||
- `/sprites/background/stage_tile_` 없음
|
||||
- `dist/46`에도 새 SVG 에셋이 정상 복사됨
|
||||
- Quick Look 썸네일로 새 기체/배경 SVG 렌더링 확인
|
||||
|
||||
## 주의 사항
|
||||
|
||||
레거시 PNG 파일은 아직 `public/sprites`와 빌드 결과물에 남아 있다.
|
||||
|
||||
하지만 현재 런타임 코드에서는 더 이상 직접 참조하지 않는다.
|
||||
|
||||
후속으로 정리할 수 있는 선택지:
|
||||
|
||||
- 레거시 PNG를 `legacy/` 폴더로 이동
|
||||
- 더 이상 쓰지 않는 파일을 삭제
|
||||
- 에셋 매니페스트를 만들어 참조 가능한 런타임 에셋을 중앙 관리
|
||||
|
||||
현재는 안정성을 위해 삭제하지 않고 경로만 확실히 교체했다.
|
||||
@@ -0,0 +1,18 @@
|
||||
# [[Error Handling in 2025]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
2025년의 프론트엔드 에러 처리는 런타임 실패에 대한 복원력을 갖추고 프로덕션 환경에서 발생할 수 있는 문제를 선제적으로 관리하는 것을 목표로 합니다 [1]. 핵심적으로 React의 에러 경계(Error Boundaries)를 사용하여 UI의 일부분에서 발생한 에러가 전체 애플리케이션의 충돌("백지 화면")로 이어지는 것을 방지하고 사용자에게 대체 UI를 제공합니다 [1, 2]. 이와 더불어 Sentry나 LogRocket과 같은 강력한 클라우드 로깅 및 모니터링 도구를 연동하여 에러를 추적하고, 세션 리플레이 및 그룹화 기능을 통해 원인을 신속하게 디버깅하는 것이 확장 가능한 애플리케이션의 모범 사례로 자리 잡았습니다 [3, 4].
|
||||
|
||||
## 📖 Core Content
|
||||
* **에러 경계(Error Boundaries)의 역할과 구현:** React의 에러 경계는 하위 컴포넌트 트리의 렌더링, 생명주기 메서드 및 생성자에서 발생하는 JavaScript 에러를 포착하는 특별한 클래스 컴포넌트입니다 [2, 5]. 에러가 발생했을 때 애플리케이션의 전체 React 컴포넌트 트리가 마운트 해제되는 것을 방지하고 사용자 친화적인 폴백(Fallback) UI를 렌더링합니다 [2, 6]. 에러 경계는 클래스 컴포넌트에 `static getDerivedStateFromError()` 또는 `componentDidCatch()` 생명주기 메서드를 정의하여 만들 수 있습니다 [7]. 함수형 컴포넌트에서는 에러 경계를 직접 만들 수 없으므로 `react-error-boundary`와 같은 라이브러리의 훅(Hook) 기반 래퍼를 활용해야 합니다 [8].
|
||||
* **에러 경계의 한계와 자바스크립트 표준 에러 처리:** 에러 경계는 만능이 아니며, 이벤트 핸들러, `setTimeout` 등의 비동기 코드, 서버 사이드 렌더링(SSR), 그리고 에러 경계 자체에서 발생한 에러는 포착하지 못합니다 [7, 8]. 이러한 예외 상황들은 표준 JavaScript의 `try-catch` 구문을 사용하여 별도로 처리해야 합니다 [8-10].
|
||||
* **전략적 배치 (Strategic Placement):** 전체 애플리케이션을 단일 에러 경계로 감싸는 것보다 서드파티 위젯, 차트, 복잡한 폼 등 불안정한 UI 섹션을 개별적으로 감싸는 것이 권장됩니다 [1, 4]. 이를 통해 특정 컴포넌트에서 에러가 발생하더라도 애플리케이션의 나머지 부분은 계속 정상적으로 상호작용할 수 있도록 격리할 수 있습니다 [1, 11].
|
||||
* **프로덕션 모니터링 및 로깅 도구 통합:** 프로덕션 환경의 복잡한 JavaScript 에러를 단순히 `console.log`로 디버깅하는 것은 비효율적입니다 [12]. 2025년의 프론트엔드 시스템은 Sentry, LogRocket, SigNoz와 같은 가시성(Observability) 및 프로덕션 모니터링 도구를 에러 경계와 통합하여 사용합니다 [3, 4]. 이러한 도구들은 중복된 에러의 지능적 그룹화 기능을 제공하며, 에러 발생 전 사용자의 행동을 기록하는 세션 리플레이(Session Replay) 기능 등을 통해 스택 추적만으로는 알 수 없는 귀중한 디버깅 컨텍스트를 제공합니다 [3].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[React Error Boundaries]], [[Debugging Frontend Applications]], [[Production Monitoring and Observability]]
|
||||
- **Projects/Contexts:** [[Scalable Frontend Architecture]], [[Sentry and LogRocket Integration]]
|
||||
- **Contradictions/Notes:** 현대 React 개발은 거의 대부분 함수형 컴포넌트와 훅(Hooks)을 중심으로 이루어지고 있지만, 에러 경계(Error Boundary) 기능만큼은 여전히 클래스 컴포넌트로만 직접 작성해야 한다는 구조적 제약이 존재합니다 [8, 13].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-26*
|
||||
@@ -0,0 +1,35 @@
|
||||
# [[Performance Optimization]]
|
||||
|
||||
## 📌 Brief Summary
|
||||
성능 최적화(Performance Optimization)는 프런트엔드 애플리케이션의 렌더링 속도, 네트워크 로딩 시간, 그리고 메모리 사용량을 개선하여 원활한 사용자 경험을 제공하는 핵심 과정입니다. React 생태계에서는 불필요한 리렌더링 방지, 코드 스플리팅, 효율적인 상태 관리, 가상화(Virtualization) 기법 도입 등을 통해 확장 가능하고(scalable) 빠른 웹 애플리케이션을 구축합니다. 최적화를 적용하기 전에는 항상 프로파일링 도구를 통해 병목 현상을 먼저 측정하고 분석하는 것이 원칙입니다.
|
||||
|
||||
## 📖 Core Content
|
||||
* **렌더링 및 메모이제이션 최적화**
|
||||
* React에서 컴포넌트는 상태, props, 컨텍스트가 변경되거나 부모 컴포넌트가 렌더링될 때 리렌더링됩니다 [1]. 불필요한 리렌더링을 막기 위해 `React.memo()`, `useCallback`, `useMemo`를 사용할 수 있지만, 얕은 비교(shallow comparison)나 객체 생성 비용 등의 오버헤드가 발생할 수 있으므로 반드시 측정 후 도입해야 합니다 [2-4].
|
||||
* JSX 내부의 익명 함수는 렌더링마다 새로운 참조를 생성하여 자식 컴포넌트의 리렌더링을 유발하므로 피하는 것이 좋습니다 [5].
|
||||
* 2025년에 안정화된 React Compiler를 도입하면, 수동으로 메모이제이션을 추가할 필요 없이 빌드 타임에 컴파일러가 자동으로 JSX 요소와 연산을 캐싱하여 코드를 깔끔하게 유지할 수 있습니다 [6-8].
|
||||
|
||||
* **코드 스플리팅 및 번들 크기 축소**
|
||||
* 초기 로드 속도를 개선하기 위해 거대한 JavaScript 번들을 작게 나누는 코드 스플리팅(Code Splitting)이 필수적입니다 [9, 10].
|
||||
* Vite 환경에서는 `manualChunks`를 설정하여 거의 변경되지 않는 무거운 벤더 라이브러리(예: React 코어, 차트 라이브러리)를 별도의 파일로 분리하고, 브라우저 캐싱을 극대화합니다 [11, 12].
|
||||
* 개별 라우트나 무거운 UI 위젯은 `React.lazy()`와 `<Suspense>`를 결합해 사용자가 접근할 때만 동적으로 지연 로딩(Lazy Loading)되도록 구현합니다 [12-14].
|
||||
|
||||
* **효율적인 상태 관리와 리렌더링 제어**
|
||||
* React의 기본 Context API는 내부의 특정 값 하나만 변경되어도 해당 컨텍스트를 구독하는 모든 하위 컴포넌트를 리렌더링하는 문제가 있습니다 [15, 16].
|
||||
* 이를 방지하기 위해 컨텍스트를 도메인별로 작게 쪼개거나, 필요한 상태 조각(slice)만 구독할 수 있는 Selector 패턴을 지원하는 Zustand, Jotai 같은 상태 관리 라이브러리를 활용하는 것이 대규모 애플리케이션 성능 관리에 유리합니다 [17-20].
|
||||
|
||||
* **대규모 리스트 렌더링과 동시성(Concurrent) 기능**
|
||||
* 수백 개 이상의 항목을 렌더링해야 하는 리스트는 DOM 비대화(DOM bloat)를 초래하므로, 화면에 보이는 항목만 렌더링하는 가상화(Windowing/Virtualization) 라이브러리(예: `react-window`)를 사용해야 하며, 리스트 렌더링 시에는 항상 안정적이고 고유한 `key`를 부여해야 합니다 [21-23].
|
||||
* React의 `useTransition`과 `useDeferredValue` 훅을 활용하면 데이터 필터링 같은 무거운 렌더링 작업을 지연시키고, 사용자 입력 등 더 중요한 상호작용의 우선순위를 높여 UI의 반응성을 유지할 수 있습니다 [24-26].
|
||||
|
||||
* **모니터링 및 메모리 누수 디버깅**
|
||||
* 최적화는 측정에서 시작됩니다. React DevTools Profiler, Chrome DevTools, `why-did-you-render` 등을 사용해 렌더링 시간과 병목을 파악하고 Core Web Vitals(LCP, INP, CLS 등)를 모니터링해야 합니다 [27-30].
|
||||
* JavaScript 메모리 누수(예: 분리된 DOM 노드, 정리되지 않은 이벤트 리스너)는 성능을 지속적으로 저하시킵니다. 이를 해결하기 위해 Chrome DevTools의 Heap Snapshot이나 Allocation Timeline 기능을 사용해 메모리를 반환하지 못하는 객체를 찾아내야 합니다 [31-34].
|
||||
|
||||
## 🔗 Knowledge Connections
|
||||
- **Related Topics:** [[React Architecture]], [[State Management]], [[Clean Code]], [[Debugging]], [[Vite and Bundling]]
|
||||
- **Projects/Contexts:** [[대규모 React 애플리케이션 개발]], [[Next.js 및 Server Components 적용 프로젝트]], [[웹 성능 최적화(Core Web Vitals) 개선 작업]]
|
||||
- **Contradictions/Notes:** 소스에 따르면, 메모이제이션(`React.memo`, `useCallback` 등)은 무조건 성능을 향상시키는 것이 아니라, 컴포넌트 렌더링이 매우 빠르거나 props가 빈번하게 변경되는 경우에는 상태 비교(comparison) 비용이 렌더링 비용보다 커져 오히려 성능을 저하시킬 수 있으므로 프로파일링을 통한 측정이 우선되어야 한다고 경고합니다 [3, 35].
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-26*
|
||||
Reference in New Issue
Block a user