performance-optimization

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Performance Optimization

性能优化

When to use this skill

何时使用此技能

  • 느린 페이지 로드: Lighthouse 점수 낮음
  • 느린 렌더링: 사용자 인터랙션 지연
  • 큰 번들 크기: 다운로드 시간 증가
  • 느린 쿼리: 데이터베이스 병목
  • 页面加载缓慢:Lighthouse评分较低
  • 渲染缓慢:用户交互延迟
  • 包体积过大:下载时间增加
  • 查询缓慢:数据库瓶颈

Instructions

操作步骤

Step 1: 성능 측정

步骤1:性能测量

Lighthouse (Chrome DevTools):
bash
undefined
Lighthouse (Chrome DevTools):
bash
undefined

CLI

CLI

npm install -g lighthouse lighthouse https://example.com --view
npm install -g lighthouse lighthouse https://example.com --view

CI에서 자동화

CI中自动化

lighthouse https://example.com --output=json --output-path=./report.json

**Web Vitals 측정** (React):
```typescript
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);
lighthouse https://example.com --output=json --output-path=./report.json

**Web Vitals测量** (React):
```typescript
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);

Step 2: React 최적화

步骤2:React优化

React.memo (불필요한 리렌더링 방지):
tsx
// ❌ 나쁜 예: 부모가 리렌더링될 때마다 자식도 리렌더링
function ExpensiveComponent({ data }: { data: Data }) {
  return <div>{/* 복잡한 렌더링 */}</div>;
}

// ✅ 좋은 예: props 변경 시에만 리렌더링
const ExpensiveComponent = React.memo(({ data }: { data: Data }) => {
  return <div>{/* 복잡한 렌더링 */}</div>;
});
useMemo & useCallback:
tsx
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:
tsx
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>
  );
}
React.memo(避免不必要的重渲染):
tsx
// ❌ 反面示例:父组件重渲染时子组件也跟着重渲染
function ExpensiveComponent({ data }: { data: Data }) {
  return <div>{/* 复杂渲染逻辑 */}</div>;
}

// ✅ 正面示例:仅在props变化时重渲染
const ExpensiveComponent = React.memo(({ data }: { data: Data }) => {
  return <div>{/* 复杂渲染逻辑 */}</div>;
});
useMemo & useCallback:
tsx
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>
  );
}
懒加载与代码分割:
tsx
import { lazy, Suspense } from 'react';

// ✅ 基于路由的代码分割
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/profile" element={<Profile />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

// ✅ 基于组件的懒加载
const HeavyChart = lazy(() => import('./components/HeavyChart'));

function Dashboard() {
  return (
    <div>
      <h1>仪表盘</h1>
      <Suspense fallback={<Skeleton />}>
        <HeavyChart data={data} />
      </Suspense>
    </div>
  );
}

Step 3: 번들 크기 최적화

步骤3:包体积优化

Webpack Bundle Analyzer:
bash
npm install --save-dev webpack-bundle-analyzer
Webpack Bundle Analyzer:
bash
npm install --save-dev webpack-bundle-analyzer

package.json

package.json

{ "scripts": { "analyze": "webpack-bundle-analyzer build/stats.json" } }

**Tree Shaking (사용하지 않는 코드 제거)**:
```typescript
// ❌ 나쁜 예: 전체 라이브러리 임포트
import _ from 'lodash';

// ✅ 좋은 예: 필요한 것만 임포트
import debounce from 'lodash/debounce';
Dynamic Imports:
typescript
// ✅ 필요할 때만 로드
button.addEventListener('click', async () => {
  const { default: Chart } = await import('chart.js');
  new Chart(ctx, config);
});
{ "scripts": { "analyze": "webpack-bundle-analyzer build/stats.json" } }

**Tree Shaking(移除未使用代码)**:
```typescript
// ❌ 反面示例:导入整个库
import _ from 'lodash';

// ✅ 正面示例:仅导入所需部分
import debounce from 'lodash/debounce';
动态导入:
typescript
// ✅ 仅在需要时加载
button.addEventListener('click', async () => {
  const { default: Chart } = await import('chart.js');
  new Chart(ctx, config);
});

Step 4: 이미지 최적화

步骤4:图片优化

Next.js Image 컴포넌트:
tsx
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 포맷 사용:
html
<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="Fallback">
</picture>
Next.js Image组件:
tsx
import Image from 'next/image';

function ProductImage() {
  return (
    <Image
      src="/product.jpg"
      alt="产品"
      width={500}
      height={500}
      priority  // 若为LCP图片
      placeholder="blur"  // 模糊占位图
      sizes="(max-width: 768px) 100vw, 50vw"
    />
  );
}
使用WebP格式:
html
<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="降级备用图">
</picture>

Step 5: 데이터베이스 쿼리 최적화

步骤5:数据库查询优化

N+1 쿼리 문제 해결:
typescript
// ❌ 나쁜 예: 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번 쿼리
인덱스 추가:
sql
-- 느린 쿼리 식별
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

-- 인덱스 추가
CREATE INDEX idx_users_email ON users(email);

-- 복합 인덱스
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
캐싱 (Redis):
typescript
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;
}
解决N+1查询问题:
typescript
// ❌ 反面示例:N+1查询
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次查询
添加索引:
sql
-- 识别慢查询
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

-- 添加索引
CREATE INDEX idx_users_email ON users(email);

-- 复合索引
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
缓存(Redis):
typescript
async function getUserProfile(userId: string) {
  // 1. 检查缓存
  const cached = await redis.get(`user:${userId}`);
  if (cached) {
    return JSON.parse(cached);
  }

  // 2. 查询数据库
  const user = await db.user.findUnique({ where: { id: userId } });

  // 3. 存入缓存(有效期1小时)
  await redis.setex(`user:${userId}`, 3600, JSON.stringify(user));

  return user;
}

Output format

输出格式

성능 최적화 체크리스트

性能优化检查表

markdown
undefined
markdown
undefined

Frontend

前端

  • React.memo로 불필요한 리렌더링 방지
  • useMemo/useCallback 적절히 사용
  • Lazy loading & Code splitting
  • 이미지 최적화 (WebP, lazy loading)
  • 번들 크기 분석 및 감소
  • 使用React.memo避免不必要的重渲染
  • 合理使用useMemo/useCallback
  • 懒加载与代码分割
  • 图片优化(WebP、懒加载)
  • 包体积分析与缩减

Backend

后端

  • N+1 쿼리 제거
  • 데이터베이스 인덱스 추가
  • Redis 캐싱
  • API Response 압축 (gzip)
  • CDN 사용
  • 消除N+1查询
  • 添加数据库索引
  • Redis缓存
  • API响应压缩(gzip)
  • 使用CDN

측정

测量

  • Lighthouse 점수 90+
  • LCP < 2.5s
  • FID < 100ms
  • CLS < 0.1
undefined
  • Lighthouse评分达到90+
  • LCP < 2.5秒
  • FID < 100毫秒
  • CLS < 0.1
undefined

Constraints

约束条件

필수 규칙 (MUST)

必须遵守的规则(MUST)

  1. 측정 먼저: 추측하지 말고 프로파일링
  2. 점진적 개선: 한 번에 하나씩 최적화
  3. 성능 모니터링: 지속적으로 추적
  1. 先测量再优化:不要凭猜测,先进行性能分析
  2. 逐步优化:一次只优化一个点
  3. 持续监控性能:持续跟踪性能指标

금지 사항 (MUST NOT)

禁止事项(MUST NOT)

  1. 조기 최적화: 병목이 없는데 최적화하지 않음
  2. 가독성 희생: 성능을 위해 코드를 복잡하게 만들지 않음
  1. 过早优化:在没有瓶颈的情况下不要进行优化
  2. 牺牲可读性:不要为了性能而让代码变得复杂难懂

Best practices

最佳实践

  1. 80/20 법칙: 20% 노력으로 80% 개선
  2. 사용자 중심: 실제 사용자 경험 개선에 집중
  3. 자동화: CI에서 성능 회귀 테스트
  1. 80/20法则:用20%的努力获得80%的性能提升
  2. 以用户为中心:专注于改善实际用户体验
  3. 自动化:在CI中进行性能回归测试

References

参考资料

Metadata

元数据

버전

版本

  • 현재 버전: 1.0.0
  • 최종 업데이트: 2025-01-01
  • 호환 플랫폼: Claude, ChatGPT, Gemini
  • 当前版本:1.0.0
  • 最后更新:2025-01-01
  • 兼容平台:Claude, ChatGPT, Gemini

관련 스킬

相关技能

  • database-schema-design
  • ui-components
  • database-schema-design
  • ui-components

태그

标签

#performance
#optimization
#React
#caching
#lazy-loading
#web-vitals
#code-quality
#performance
#optimization
#React
#caching
#lazy-loading
#web-vitals
#code-quality

Examples

示例

Example 1: Basic usage

示例1:基础用法

<!-- Add example content here -->
<!-- 在此添加示例内容 -->

Example 2: Advanced usage

示例2:高级用法

<!-- Add advanced example content here -->
<!-- 在此添加高级示例内容 -->