스로틀링 패턴(Throttling Pattern)은 서비스에 대한 요청 비율을 제한해 과부하를 방지하는 패턴이다. 레이트 리미팅(Rate Limiting)이라고도 하며, API 게이트웨이와 서비스 보호에 필수적이다.
주요 알고리즘
토큰 버킷 (Token Bucket)
버킷에 토큰이 일정 속도로 채워짐
요청 시 토큰 1개 소비
토큰 없으면 요청 거절
장점: 버스트 허용 (버킷이 가득 찬 경우)
용도: API 클라이언트 레이트 리밋
슬라이딩 윈도우 (Sliding Window)
최근 N초 동안의 요청 수를 카운트
정확하지만 메모리 더 필요
고정 윈도우의 경계 문제 해결:
고정: 0:59에 100개 + 1:01에 100개 = 2초에 200개
슬라이딩: 항상 최근 60초 = 최대 100개
typescript
// 슬라이딩 윈도우 레이트 리미터
async function isAllowed(
userId: string,
limitPerMinute: number
): Promise<boolean> {
const key = `ratelimit:${userId}`;
const now = Date.now();
const windowStart = now - 60000; // 1분
const pipe = redis.pipeline();
pipe.zremrangebyscore(key, 0, windowStart); // 오래된 요청 제거
pipe.zadd(key, now, `${now}-${Math.random()}`); // 현재 요청 추가
pipe.zcard(key); // 카운트
pipe.expire(key, 60); // TTL
const results = await pipe.exec();
const count = results![2][1] as number;
return count <= limitPerMinute;
}
API Gateway 설정 (Kong)
yaml
plugins:
- name: rate-limiting
config:
minute: 100 # 분당 100회
hour: 1000 # 시간당 1000회
policy: redis # Redis로 분산 카운팅
limit_by: consumer # 사용자별 제한
error_message: "Rate limit exceeded. Try again in 1 minute."
스로틀링 응답 설계
HTTP 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1716134400
클라이언트 대응:
1. Retry-After 헤더 읽기
2. 지수 백오프 적용
3. 큐에 넣고 나중에 재시도
관련 개념