diff --git a/.claude/commands/optimize.md b/.claude/commands/optimize.md new file mode 100644 index 0000000..0dfe632 --- /dev/null +++ b/.claude/commands/optimize.md @@ -0,0 +1,249 @@ +# Performance Optimization Analysis Command + +Analyze the blog codebase from a performance optimization perspective and provide improvement recommendations as a senior frontend developer. + +## Input + +$ARGUMENTS: Analysis target (optional) +- Specific file path: `src/app/post/[id]/page.tsx` +- Specific directory: `src/app/_components/` +- Analysis type: `bundle`, `rendering`, `data-fetching`, `images` +- If empty: Full codebase analysis + +## Reference Skill + +**Always analyze based on rules from `.claude/skills/react-best-practices/SKILL.md`.** + +Individual rule details: `.claude/skills/react-best-practices/rules/*.md` + +## Analysis Process + +### 1. Priority 1: Eliminating Waterfalls (CRITICAL) + +**Related rules:** `async-*` + +```bash +# Promise.all usage +grep -r "Promise.all" src/ --include="*.tsx" --include="*.ts" + +# Sequential await patterns (potential Waterfall) - async-parallel violation +grep -rn "await" src/ --include="*.tsx" | head -30 + +# Suspense boundary usage - async-suspense-boundaries +grep -r "" src/ --include="*.tsx" | head -20 +grep -r "style={{" src/ --include="*.tsx" | head -20 + +# useCallback/useMemo usage +grep -r "useCallback\|useMemo" src/ --include="*.tsx" + +# useEffect dependencies - rerender-dependencies +grep -r "useEffect" src/ --include="*.tsx" -A 3 | head -40 +``` + +**Checklist:** +- [ ] `rerender-memo`: Extract expensive work into memoized components +- [ ] `rerender-dependencies`: Use primitive dependencies in effects +- [ ] `rerender-functional-setstate`: Use functional setState for stable callbacks +- [ ] `rerender-lazy-state-init`: Pass function to useState for expensive initialization + +### 6. Priority 6: Rendering Performance (MEDIUM) + +**Related rules:** `rendering-*` + +```bash +# Conditional rendering pattern - rendering-conditional-render +grep -r "&& <" src/ --include="*.tsx" | head -20 + +# content-visibility usage - rendering-content-visibility +grep -r "content-visibility" src/ --include="*.scss" + +# Static JSX hoisting - rendering-hoist-jsx +grep -r "const.*=.*<" src/ --include="*.tsx" | head -20 +``` + +**Checklist:** +- [ ] `rendering-conditional-render`: Use ternary instead of && +- [ ] `rendering-content-visibility`: Use content-visibility for long lists +- [ ] `rendering-hoist-jsx`: Extract static JSX outside components + +### 7. Priority 7: JavaScript Performance (LOW-MEDIUM) + +**Related rules:** `js-*` + +```bash +# RegExp in loops - js-hoist-regexp +grep -rn "new RegExp" src/ --include="*.ts" --include="*.tsx" + +# Array method chaining - js-combine-iterations +grep -r "\.filter.*\.map\|\.map.*\.filter" src/ --include="*.tsx" +``` + +**Checklist:** +- [ ] `js-hoist-regexp`: Hoist RegExp creation outside loops +- [ ] `js-combine-iterations`: Combine multiple filter/map into one loop +- [ ] `js-set-map-lookups`: Use Set/Map for O(1) lookups + +### 8. Image Optimization + +```bash +# Next.js Image component usage +grep -r "from \"next/image\"" src/ +grep -r "(query = GET_META_FIELDS): Promise => { + // 기존 로직 +}; + +export const getPosts = cache(_getPosts); +``` + +### P1 - High (1주 내 적용) + +- [ ] **Shiki dynamic import 적용** (`bundle-dynamic-imports`) + - 파일: `src/app/post/[id]/Markdown/_components/Code.tsx` + - 문제: shiki는 번들 사이즈가 큰 라이브러리 + - 개선: dynamic import로 코드 스플리팅 + +```typescript +const highlightCode = async (code: string, language: string) => { + const { codeToHtml } = await import("shiki"); + return codeToHtml(code, { lang: language, theme: "github-dark" }); +}; +``` + +- [ ] **Barrel imports 제거** (`bundle-barrel-imports`) + - 파일: `src/types/index.ts` + - 문제: `export * from` 패턴이 tree-shaking 방해 + - 개선: 직접 import 사용 + - Before: `import { PostType } from "@/types"` + - After: `import { PostType } from "@/types/apiResponseType"` + +### P2 - Medium (2주 내 적용) + +- [ ] **Fuse.js lazy loading** (`bundle-conditional`) + - 파일: `src/app/_components/Search/index.tsx` + - 문제: 검색 기능이 항상 필요하지 않음 + - 개선: Search 컴포넌트 진입 시점에 dynamic import 고려 + +- [ ] **content-visibility 적용** (`rendering-content-visibility`) + - 파일: Posts 컴포넌트 스타일 + - 적용 시점: 포스트 목록이 많아질 경우 + +--- + +## 잘 적용된 부분 (전체 분석) + +| 패턴 | 위치 | 상태 | +|------|------|------| +| Promise.all 병렬 페칭 | `SidebarWrapper/index.tsx:11` | ✅ | +| Suspense boundaries | `layout.tsx:122`, `Markdown/index.tsx:40` | ✅ | +| Third-party 지연 로딩 | `layout.tsx:69,81` (afterInteractive) | ✅ | +| 데이터 직렬화 최적화 | `PostWithoutMarkdownType`, `Pick<>` 사용 | ✅ | +| Next/Image 사용 | `Cards`, `MarkdownImage`, `Heading` | ✅ | +| useMemo 적용 | `Search/index.tsx:17` (Fuse 인스턴스) | ✅ | +| useDebounce 적용 | 검색 입력 최적화 | ✅ | + +--- + +## `posts/page.tsx` 컴포넌트 트리 분석 결과 ## 컴포넌트 트리 구조 @@ -84,4 +156,4 @@ posts/page.tsx (Server Component) --- -*Generated: 2026-01-17* +*Last Updated: 2026-01-18*