.agents/skills/performance-optimization/SKILL.md
Optimize application performance for speed, efficiency, and scalability. Use when improving page load times, reducing bundle size, optimizing database queries, or fixing performance bottlenecks. Handles React optimization, lazy loading, caching, code splitting, and profiling.
npx skillsauth add lildibbb/tele-crm-frontend performance-optimizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Lighthouse (Chrome DevTools):
# CLI
npm install -g lighthouse
lighthouse https://example.com --view
# CI에서 자동화
lighthouse https://example.com --output=json --output-path=./report.json
Web Vitals 측정 (React):
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric: any) {
// Google Analytics, Datadog 등으로 전송
console.log(metric);
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
React.memo (불필요한 리렌더링 방지):
// ❌ 나쁜 예: 부모가 리렌더링될 때마다 자식도 리렌더링
function ExpensiveComponent({ data }: { data: Data }) {
return <div>{/* 복잡한 렌더링 */}</div>;
}
// ✅ 좋은 예: props 변경 시에만 리렌더링
const ExpensiveComponent = React.memo(({ data }: { data: Data }) => {
return <div>{/* 복잡한 렌더링 */}</div>;
});
useMemo & useCallback:
function ProductList({ products, category }: Props) {
// ✅ 필터링 결과 메모이제이션
const filteredProducts = useMemo(() => {
return products.filter(p => p.category === category);
}, [products, category]);
// ✅ 콜백 메모이제이션
const handleAddToCart = useCallback((id: string) => {
addToCart(id);
}, []);
return (
<div>
{filteredProducts.map(product => (
<ProductCard key={product.id} product={product} onAdd={handleAddToCart} />
))}
</div>
);
}
Lazy Loading & Code Splitting:
import { lazy, Suspense } from 'react';
// ✅ Route-based code splitting
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
const Settings = lazy(() => import('./pages/Settings'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
// ✅ Component-based lazy loading
const HeavyChart = lazy(() => import('./components/HeavyChart'));
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<Skeleton />}>
<HeavyChart data={data} />
</Suspense>
</div>
);
}
Webpack Bundle Analyzer:
npm install --save-dev webpack-bundle-analyzer
# package.json
{
"scripts": {
"analyze": "webpack-bundle-analyzer build/stats.json"
}
}
Tree Shaking (사용하지 않는 코드 제거):
// ❌ 나쁜 예: 전체 라이브러리 임포트
import _ from 'lodash';
// ✅ 좋은 예: 필요한 것만 임포트
import debounce from 'lodash/debounce';
Dynamic Imports:
// ✅ 필요할 때만 로드
button.addEventListener('click', async () => {
const { default: Chart } = await import('chart.js');
new Chart(ctx, config);
});
Next.js Image 컴포넌트:
import Image from 'next/image';
function ProductImage() {
return (
<Image
src="/product.jpg"
alt="Product"
width={500}
height={500}
priority // LCP 이미지인 경우
placeholder="blur" // 블러 플레이스홀더
sizes="(max-width: 768px) 100vw, 50vw"
/>
);
}
WebP 포맷 사용:
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Fallback">
</picture>
N+1 쿼리 문제 해결:
// ❌ 나쁜 예: N+1 queries
const posts = await db.post.findMany();
for (const post of posts) {
const author = await db.user.findUnique({ where: { id: post.authorId } });
// 101번 쿼리 (1 + 100)
}
// ✅ 좋은 예: JOIN 또는 include
const posts = await db.post.findMany({
include: {
author: true
}
});
// 1번 쿼리
인덱스 추가:
-- 느린 쿼리 식별
EXPLAIN ANALYZE SELECT * FROM users WHERE email = '[email protected]';
-- 인덱스 추가
CREATE INDEX idx_users_email ON users(email);
-- 복합 인덱스
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
캐싱 (Redis):
async function getUserProfile(userId: string) {
// 1. 캐시 확인
const cached = await redis.get(`user:${userId}`);
if (cached) {
return JSON.parse(cached);
}
// 2. DB 조회
const user = await db.user.findUnique({ where: { id: userId } });
// 3. 캐시 저장 (1시간)
await redis.setex(`user:${userId}`, 3600, JSON.stringify(user));
return user;
}
## Frontend
- [ ] React.memo로 불필요한 리렌더링 방지
- [ ] useMemo/useCallback 적절히 사용
- [ ] Lazy loading & Code splitting
- [ ] 이미지 최적화 (WebP, lazy loading)
- [ ] 번들 크기 분석 및 감소
## Backend
- [ ] N+1 쿼리 제거
- [ ] 데이터베이스 인덱스 추가
- [ ] Redis 캐싱
- [ ] API Response 압축 (gzip)
- [ ] CDN 사용
## 측정
- [ ] Lighthouse 점수 90+
- [ ] LCP < 2.5s
- [ ] FID < 100ms
- [ ] CLS < 0.1
#performance #optimization #React #caching #lazy-loading #web-vitals #code-quality
development
Tiptap editor API patterns for vmark WYSIWYG development. Use when working with editor commands, node traversal, selection handling, or format operations.
tools
Expert guide for creating effective prompts for Google Stitch AI UI design tool. Use when user wants to design UI/UX in Stitch, create app interfaces, generate mobile/web designs, or needs help cra...
development
Teaches agents to iteratively build websites using Stitch with an autonomous baton-passing loop pattern
development
Provides complete shadcn/ui component library patterns including installation, configuration, and implementation of accessible React components. Use when setting up shadcn/ui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts.