docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거

Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
This commit is contained in:
Antigravity Agent
2026-07-05 00:33:48 +09:00
parent 1cfd3bbb56
commit 9148c358d0
6455 changed files with 1 additions and 86875 deletions
@@ -0,0 +1,263 @@
---
id: game-skia-native-2d
title: Skia / Native 2D — Mobile / Cross-platform 그림
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [game, skia, 2d, mobile, vibe-coding]
tech_stack: { language: "TS / Dart", applicable_to: ["Mobile", "Frontend"] }
applied_in: []
aliases: [Skia, react-native-skia, CanvasKit, Flutter, Path, paint, fast 2D]
---
# Skia / Native 2D
> Google Skia = Chrome/Flutter/Android/Firefox 의 그림 엔진. **GPU-accelerated 2D**. RN Skia / CanvasKit / Flutter Canvas 가 wrapper.
## 📖 핵심 개념
- Path: 선 + 곡선.
- Paint: 색 + style.
- Canvas: drawable surface.
- Shader / image filter: Path 위 효과.
## 💻 코드 패턴
### React Native Skia
```bash
yarn add @shopify/react-native-skia
```
```tsx
import { Canvas, Circle, Path, Skia, useClockValue, useComputedValue, useValue } from '@shopify/react-native-skia';
function App() {
const clock = useClockValue();
const cx = useComputedValue(() => 100 + Math.sin(clock.current / 500) * 50, [clock]);
return (
<Canvas style={{ flex: 1 }}>
<Circle cx={cx} cy={100} r={40} color="hotpink" />
</Canvas>
);
}
```
### Path (복잡 도형)
```tsx
const path = Skia.Path.Make();
path.moveTo(50, 50);
path.lineTo(150, 50);
path.quadTo(200, 100, 150, 150);
path.close();
<Path path={path} color="lightblue" style="fill" />
<Path path={path} color="darkblue" style="stroke" strokeWidth={2} />
```
### Gradient
```tsx
import { LinearGradient, vec } from '@shopify/react-native-skia';
<Rect x={0} y={0} width={200} height={200}>
<LinearGradient
start={vec(0, 0)}
end={vec(200, 200)}
colors={['#00ffff', '#ff00ff']}
/>
</Rect>
```
### Image filter (blur, etc)
```tsx
import { Blur, ColorMatrix } from '@shopify/react-native-skia';
<Image image={img} x={0} y={0} width={300} height={300}>
<Blur blur={10} />
<ColorMatrix matrix={[
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0.5, 0, // 50% alpha
]} />
</Image>
```
### Shader (GPU)
```tsx
import { Shader, Skia } from '@shopify/react-native-skia';
const source = Skia.RuntimeEffect.Make(`
uniform float2 iResolution;
uniform float iTime;
half4 main(float2 fragCoord) {
float2 uv = fragCoord / iResolution;
return half4(uv.x, uv.y, sin(iTime), 1.0);
}
`);
const clock = useClockValue();
const uniforms = useComputedValue(() => ({
iResolution: [width, height],
iTime: clock.current / 1000,
}), [clock]);
<Canvas>
<Fill>
<Shader source={source!} uniforms={uniforms} />
</Fill>
</Canvas>
```
→ Web 의 Three.js shader 같은 power.
### Animation (declarative)
```tsx
import { useSpring, withTiming, withRepeat, withSequence } from '@shopify/react-native-skia';
const x = useSharedValue(0);
useEffect(() => {
x.value = withRepeat(
withSequence(
withTiming(200, { duration: 1000 }),
withTiming(0, { duration: 1000 }),
),
-1
);
}, []);
<Circle cx={x} cy={100} r={20} color="red" />
```
→ Reanimated 통합 — UI thread 60fps.
### Text
```tsx
import { Text, useFont } from '@shopify/react-native-skia';
const font = useFont(require('./Roboto.ttf'), 24);
if (!font) return null;
<Text x={50} y={100} text="Hello" font={font} color="white" />
```
### CanvasKit (web)
```ts
import CanvasKitInit from 'canvaskit-wasm';
const CanvasKit = await CanvasKitInit({ locateFile: f => `/${f}` });
const surface = CanvasKit.MakeWebGLCanvasSurface('canvas')!;
const canvas = surface.getCanvas();
const paint = new CanvasKit.Paint();
paint.setColor(CanvasKit.Color4f(0.9, 0.5, 0.2, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Fill);
canvas.drawCircle(100, 100, 50, paint);
surface.flush();
```
→ Web 에서 Skia 그대로 (Flutter web 이 사용).
### Flutter Canvas
```dart
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
canvas.drawCircle(Offset(size.width / 2, size.height / 2), 50, paint);
final path = Path()
..moveTo(0, 0)
..quadraticBezierTo(100, 200, 200, 0);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter old) => false;
}
CustomPaint(painter: MyPainter(), size: Size.infinite);
```
### Game-like usage (RN Skia)
```tsx
function Game() {
const clock = useClockValue();
const playerY = useComputedValue(() => 200 + Math.sin(clock.current / 500) * 50, [clock]);
// Bullets — array of values
const bullets = useMemo(() => Array.from({ length: 20 }, () => ({ x: 0, y: 0 })), []);
return (
<Canvas style={{ flex: 1, backgroundColor: 'black' }}>
<Circle cx={100} cy={playerY} r={20} color="green" />
{bullets.map((b, i) => (
<Circle key={i} cx={b.x} cy={b.y} r={5} color="red" />
))}
</Canvas>
);
}
```
### Performance
- Path / shape 재사용 (useMemo).
- Reanimated 의 SharedValue 가 UI thread.
- `useComputedValue` 가 derive.
- 큰 image = `Image` component + cache.
- 너무 많은 element = Canvas 가 한 번에 그림.
### Web Canvas API (대안)
```ts
const ctx = canvas.getContext('2d')!;
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 100);
ctx.beginPath();
ctx.arc(150, 150, 50, 0, Math.PI * 2);
ctx.fill();
```
→ Skia 만큼 강력 X. 단순 OK.
### vs WebGL (Three.js)
```
2D = Skia / Canvas API
3D = WebGL / WebGPU / Three.js
Skia 도 GPU 가속 — Canvas API 보다 빠름 (canvaskit).
```
## 🤔 의사결정 기준
| 상황 | 추천 |
|---|---|
| RN custom drawing | RN Skia |
| Flutter | Canvas / CustomPainter |
| Web 2D | Canvas API (간단) / CanvasKit (강력) |
| Game UI | Skia / 자체 canvas |
| 차트 | Recharts / Visx (위 문서) |
| 매우 simple shape | SVG |
## ❌ 안티패턴
- **매 frame Path 새로**: useMemo / 외부.
- **JS thread 에 animation**: reanimated SharedValue.
- **큰 Bitmap 매번 decode**: cache.
- **너무 많은 Element (1000+)**: 한 Canvas 안 묶기.
- **Shader 매 frame compile**: useMemo.
- **CanvasKit web bundle 인지**: 큰 (~3MB). Lazy.
## 🤖 LLM 활용 힌트
- RN = RN Skia (modern).
- Flutter = built-in Canvas.
- Web 2D = Canvas API 보통 충분.
- Reanimated 통합으로 60fps.
## 🔗 관련 문서
- [[RN_Reanimated_3_Patterns]]
- [[Mobile_Flutter_Patterns]]
- [[Game_Shader_Patterns]]