askill
performance

performanceSafety --Repository

성능 최적화 패턴, 캐싱 전략, 데이터베이스 최적화

0 stars
1.2k downloads
Updated 1/24/2026

Package Files

Loading files...
SKILL.md

Performance Guide

시간 복잡도 분석

Big-O 표기법

복잡도이름예시
O(1)상수해시맵 조회
O(log n)로그이진 탐색
O(n)선형배열 순회
O(n log n)선형 로그퀵소트, 머지소트
O(n²)제곱중첩 루프
O(2ⁿ)지수모든 부분집합

흔한 비효율 패턴

# Bad: O(n²) - 중첩 루프
function findDuplicates(arr):
    for i in range(len(arr)):
        for j in range(i+1, len(arr)):
            if arr[i] == arr[j]:
                return true
    return false

# Good: O(n) - 해시셋
function findDuplicates(arr):
    seen = set()
    for item in arr:
        if item in seen:
            return true
        seen.add(item)
    return false

데이터베이스 최적화

N+1 문제

# Bad: N+1 쿼리
users = db.query("SELECT * FROM users")
for user in users:
    posts = db.query("SELECT * FROM posts WHERE user_id = ?", user.id)

# Good: JOIN 또는 IN
users = db.query("""
    SELECT users.*, posts.* 
    FROM users 
    LEFT JOIN posts ON users.id = posts.user_id
""")

# 또는 두 번 쿼리
users = db.query("SELECT * FROM users")
userIds = [u.id for u in users]
posts = db.query("SELECT * FROM posts WHERE user_id IN (?)", userIds)

인덱스 전략

# 자주 검색하는 컬럼에 인덱스
CREATE INDEX idx_users_email ON users(email)

# 복합 인덱스 (순서 중요)
CREATE INDEX idx_posts_user_created ON posts(user_id, created_at)

# 커버링 인덱스
CREATE INDEX idx_users_covering ON users(email, name, status)

# 인덱스가 사용되지 않는 경우
WHERE LOWER(email) = 'test'  # 함수 사용
WHERE status != 'active'     # 부정 조건
WHERE name LIKE '%test'      # 앞 와일드카드

쿼리 최적화

# Bad: SELECT *
SELECT * FROM users WHERE status = 'active'

# Good: 필요한 컬럼만
SELECT id, name, email FROM users WHERE status = 'active'

# Bad: 큰 OFFSET
SELECT * FROM posts ORDER BY created_at LIMIT 20 OFFSET 10000

# Good: Cursor 기반
SELECT * FROM posts 
WHERE created_at < ?last_cursor 
ORDER BY created_at DESC 
LIMIT 20

캐싱 전략

캐시 레이어

요청 → 1. 브라우저 캐시
      → 2. CDN
      → 3. 애플리케이션 캐시 (Redis)
      → 4. 데이터베이스 쿼리 캐시
      → 5. 데이터베이스

캐시 패턴

# Cache-Aside (Lazy Loading)
function getUser(userId):
    user = cache.get("user:" + userId)
    if user:
        return user
    
    user = db.users.findById(userId)
    cache.set("user:" + userId, user, ttl=3600)
    return user

# Write-Through
function updateUser(userId, data):
    user = db.users.update(userId, data)
    cache.set("user:" + userId, user)
    return user

# Cache Invalidation
function deleteUser(userId):
    db.users.delete(userId)
    cache.delete("user:" + userId)

TTL 전략

# 데이터 특성별 TTL
CACHE_TTL = {
    "user_profile": 3600,      # 1시간 (자주 안 바뀜)
    "user_session": 1800,      # 30분
    "product_list": 300,       # 5분 (자주 바뀜)
    "static_config": 86400,    # 24시간
}

비동기 처리

작업 큐

# 동기 처리 (느림)
function signup(user):
    createUser(user)
    sendWelcomeEmail(user)    # 3초
    createAnalytics(user)     # 2초
    return user               # 총 5초+

# 비동기 처리 (빠름)
function signup(user):
    createUser(user)
    queue.enqueue("send_welcome_email", user)
    queue.enqueue("create_analytics", user)
    return user               # 즉시 반환

배치 처리

# Bad: 개별 처리
for item in items:
    db.insert(item)  # N번 DB 호출

# Good: 배치 처리
db.insertMany(items)  # 1번 DB 호출

# 청크 처리 (메모리 관리)
CHUNK_SIZE = 1000
for chunk in chunks(items, CHUNK_SIZE):
    db.insertMany(chunk)

메모리 최적화

메모리 누수 방지

# Bad: 이벤트 리스너 누수
function Component:
    onMount:
        window.addEventListener("resize", this.handleResize)
    # cleanup 없음!

# Good: cleanup
function Component:
    onMount:
        window.addEventListener("resize", this.handleResize)
    onUnmount:
        window.removeEventListener("resize", this.handleResize)

대용량 데이터 처리

# Bad: 전체 메모리 로드
data = file.readAll()  # 10GB 파일 → 메모리 부족

# Good: 스트리밍
for chunk in file.readChunks(1024 * 1024):  # 1MB씩
    process(chunk)

# Generator 사용
function processLargeData(items):
    for item in items:
        yield transform(item)  # 하나씩 처리

프론트엔드 최적화

번들 최적화

// 코드 스플리팅
import("./heavyModule").then(module => {
    module.init()
})

// Tree Shaking
import { used } from "library"  // unused는 번들에서 제외
<!-- 이미지 최적화 -->
<img src="image.jpg" 
     loading="lazy" 
     srcset="small.jpg 300w, large.jpg 1000w">

렌더링 최적화

# Bad: 불필요한 리렌더
function Parent:
    render:
        <Child data={this.state.data} />

# Good: 메모이제이션
MemoizedChild = memo(Child)

function Parent:
    render:
        <MemoizedChild data={this.state.data} />

# 가상화 (긴 목록)
<VirtualList
    items={largeList}
    itemHeight={50}
    renderItem={item => <Item data={item} />}
/>

성능 측정

백엔드 메트릭

# 응답 시간
p50: 50ms    # 중앙값
p95: 200ms   # 95% 요청
p99: 500ms   # 99% 요청

# 처리량
RPS: 1000    # 초당 요청 수

# 에러율
Error Rate < 0.1%

프론트엔드 메트릭

# Core Web Vitals
LCP (Largest Contentful Paint): < 2.5s
FID (First Input Delay): < 100ms
CLS (Cumulative Layout Shift): < 0.1

성능 체크리스트

데이터베이스

  • 자주 검색하는 컬럼에 인덱스
  • N+1 쿼리 제거
  • 필요한 컬럼만 SELECT
  • 큰 OFFSET 대신 Cursor 사용

캐싱

  • 자주 읽는 데이터 캐시
  • 적절한 TTL 설정
  • 캐시 무효화 전략

코드

  • O(n²) 이상 알고리즘 최적화
  • 메모리 누수 방지
  • 비동기 처리 활용
  • 배치 처리 활용

관련 스킬

  • code-quality: 코드 최적화 원칙
  • debugging: 성능 문제 분석

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

AI review pending.

Metadata

Licenseunknown
Version-
Updated1/24/2026
Publisherjaeyeonling

Tags

databasetesting