소스 정보
- 저장소
- miles990/claude-software-skills
- 최근 소스 활동
- 2026년 1월 8일 02:34
- 감지된 SKILL.md 언어
- 영어
- 스타
- 20
- 포크
- 5
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/miles990/claude-software-skills --skill performance-optimization명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Enterprise-grade repository analysis with arc42/C4 architecture documentation, technical debt quantification, security assessment, and multi-stakeholder reporting
Claude Code Plugin 開發、發布、安裝、更新與 Marketplace 管理完整指南
Flame Engine core fundamentals - components, input, collision, camera, animation, scenes
SOC 직업 분류 기준
SKILL.md 표시 중
| name | performance-optimization |
| description | Profiling, optimization techniques, and performance best practices |
| domain | software-engineering |
| version | 1.0.0 |
| tags | ["performance","profiling","optimization","caching","database","frontend"] |
| triggers | {"keywords":{"primary":["performance","optimize","optimization","profiling","benchmark","speed"],"secondary":["caching","latency","throughput","memory","cpu","bottleneck","lighthouse"]},"context_boost":["slow","fast","improve","scale"],"context_penalty":["design","architecture","security"],"priority":"high"} |
Measure first, optimize second. This guide covers profiling techniques and optimization strategies.
1. Don't optimize prematurely
2. Measure before optimizing
3. Optimize the biggest bottleneck first
4. Measure again to verify improvement
// Using Node.js built-in profiler
// Start with: node --prof app.js
// Process: node --prof-process isolate-*.log > profile.txt
// Or use clinic.js
// npm install -g clinic
// clinic doctor -- node app.js
// clinic flame -- node app.js
// Programmatic profiling
import { performance, PerformanceObserver } from 'perf_hooks';
const obs = new PerformanceObserver((items) => {
items.getEntries().forEach((entry) => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('start');
await expensiveOperation();
performance.mark('end');
performance.measure('expensive-op', 'start', 'end');
// Check memory usage
console.log(process.memoryUsage());
// {
// rss: 30000000, // Resident Set Size - total memory
// heapTotal: 7000000, // V8 heap total
// heapUsed: 5000000, // V8 heap used
// external: 800000 // C++ objects bound to JS
// }
// Take heap snapshot
const v8 = require('v8');
const fs = require('fs');
const snapshotFile = `heap-${Date.now()}.heapsnapshot`;
const snapshot = v8.writeHeapSnapshot(snapshotFile);
// Open in Chrome DevTools Memory tab
-- ❌ Slow: SELECT * and no index
SELECT * FROM orders WHERE user_id = 123;
-- ✅ Better: Select only needed columns, with index
CREATE INDEX idx_orders_user_id ON orders(user_id);
SELECT id, total, status FROM orders WHERE user_id = 123;
-- ❌ N+1 query problem
-- For each user, query their orders (100 users = 101 queries)
SELECT * FROM users;
SELECT * FROM orders WHERE user_id = 1;
SELECT * FROM orders WHERE user_id = 2;
...
-- ✅ Single query with JOIN
SELECT u.*, o.* FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- Or batch loading
SELECT * FROM orders WHERE user_id IN (1, 2, 3, ...);
EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01'
GROUP BY u.id
ORDER BY order_count DESC
LIMIT 10;
-- Output shows:
-- - Execution plan (Seq Scan vs Index Scan)
-- - Estimated vs actual rows
-- - Time per operation
-- - Total execution time
-- Single column index
CREATE INDEX idx_users_email ON users(email);
-- Composite index (order matters!)
-- Good for: WHERE status = 'active' AND created_at > '2024-01-01'
CREATE INDEX idx_orders_status_created ON orders(status, created_at);
-- Partial index (smaller, faster for filtered queries)
CREATE INDEX idx_active_users ON users(email)
WHERE status = 'active';
-- Covering index (includes all needed columns)
CREATE INDEX idx_orders_user_covering ON orders(user_id)
INCLUDE (total, status, created_at);
-- When NOT to index:
-- - Small tables
-- - Columns with low cardinality (e.g., boolean)
-- - Frequently updated columns
-- - Write-heavy tables
// Cache-aside pattern
async function getUser(id: string): Promise<User> {
// Try cache first
const cached = await cache.get(`user:${id}`);
if (cached) return JSON.parse(cached);
// Cache miss - fetch from DB
const user = await db.users.findById(id);
// Store in cache
if (user) {
await cache.set(`user:${id}`, JSON.stringify(user), 'EX', 3600);
}
return user;
}
// Write-through pattern
async function updateUser(id: string, data: Partial<User>): Promise<User> {
// Update DB
const user = await db.users.update(id, data);
// Update cache immediately
cache.(, .(user), , );
user;
}
// Event-based invalidation
eventBus.on('user:updated', async (userId: string) => {
await cache.del(`user:${userId}`);
await cache.del(`user:${userId}:orders`);
});
// Tag-based invalidation
async function invalidateUserRelated(userId: string) {
const keys = await cache.keys(`*:user:${userId}:*`);
if (keys.length > 0) {
await cache.del(...keys);
}
}
// Version-based cache busting
const CACHE_VERSION = 'v2';
const cacheKey = `${CACHE_VERSION}:user:${id}`;
// Simple memoization
function memoize<T extends (...args: any[]) => any>(fn: T): T {
const cache = new Map();
return ((...args: Parameters<T>) => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn(...args);
cache.set(key, result);
return result;
}) as T;
}
// With TTL
function memoizeWithTTL<T extends (...args: any[]) => any>(
fn: T,
ttlMs: number
): T {
const cache = new Map<string, { value: any; expires: number }>();
return ((...args: Parameters<T>) => {
const key = JSON.stringify(args);
cached = cache.(key);
(cached && cached. > .()) {
cached.;
}
result = (...args);
cache.(key, { : result, : .() + ttlMs });
result;
}) T;
}
| Metric | Good | Description |
|---|---|---|
| LCP | < 2.5s | Largest Contentful Paint |
| INP | < 200ms | Interaction to Next Paint |
| CLS | < 0.1 | Cumulative Layout Shift |
// React lazy loading
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));
function App() {
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
// Dynamic import for heavy libraries
async function processImage(file: File) {
const sharp = await import('sharp');
(file).().();
}
<!-- Responsive images -->
<img
src="image-800.jpg"
srcset="
image-400.jpg 400w,
image-800.jpg 800w,
image-1200.jpg 1200w
"
sizes="(max-width: 600px) 400px, 800px"
loading="lazy"
alt="Description"
/>
<!-- Modern formats with fallback -->
<picture>
<source srcset="image.avif" type="image/avif" />
<source srcset="image.webp" type="image/webp" />
<img src="image.jpg" alt="Description" />
</picture>
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
// Separate large libraries
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
chunks: 'all',
},
},
},
},
};
// Database connection pool
import { Pool } from 'pg';
const pool = new Pool({
max: 20, // Maximum connections
idleTimeoutMillis: 30000, // Close idle connections after 30s
connectionTimeoutMillis: 2000, // Fail if can't connect in 2s
});
// Use pool, not individual connections
async function getUser(id: string) {
const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
return result.rows[0];
}
// HTTP connection keep-alive
import http from 'http';
const agent = new http.Agent({
keepAlive: true,
maxSockets: 50,
});
fetch('https://api.example.com', { agent });
// Move slow operations out of request path
app.post('/api/orders', async (req, res) => {
// Quick: Create order
const order = await db.orders.create(req.body);
// Don't wait: Queue async tasks
await queue.add('send-confirmation-email', { orderId: order.id });
await queue.add('update-inventory', { items: order.items });
await queue.add('notify-warehouse', { orderId: order.id });
// Respond immediately
res.status(201).json(order);
});
// Process queue separately
queue.process('send-confirmation-email', async (job) => {
const order = await db.orders.findById(job.data.orderId);
await emailService.sendOrderConfirmation(order);
});
import compression from 'compression';
import express from 'express';
const app = express();
// Compress responses > 1KB
app.use(compression({
threshold: 1024,
filter: (req, res) => {
if (req.headers['x-no-compression']) {
return false;
}
return compression.filter(req, res);
}
}));
// O(n²) → O(n) with Set
// Find duplicates
function hasDuplicates(arr: number[]): boolean {
// ❌ O(n²)
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) return true;
}
}
return false;
// ✅ O(n)
const seen = new Set<number>();
for (const num of arr) {
if (seen.has(num)) return true;
seen.add(num);
}
return false;
}
// O(n) → O(1) with Map
// Lookup by key
class UserCache {
// ❌ O(n) lookup
private users: User[] = [];
find(id: string) {
return this.users.find( u. === id);
}
usersMap = <, >();
() {
..(id);
}
}
// Trade memory for speed: Precompute
class TaxCalculator {
private taxRates = new Map<string, number>();
constructor() {
// Precompute all tax rates
for (const state of US_STATES) {
this.taxRates.set(state, this.computeTaxRate(state));
}
}
// O(1) instead of O(complex calculation)
getTaxRate(state: string): number {
return this.taxRates.get(state) ?? 0;
}
}
// Application metrics
import { Counter, Histogram } from 'prom-client';
const httpRequestDuration = new Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests',
labelNames: ['method', 'route', 'status'],
buckets: [0.1, 0.5, 1, 2, 5]
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
httpRequestDuration
.labels(req.method, req.route?.path || 'unknown', res.statusCode.toString())
.observe(duration);
});
next();
});