npx skillsauth add excatt/superclaude-plusplus rate-limitInstall 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.
레이트 리밋 설계 가이드를 실행합니다.
버킷에 토큰이 일정 속도로 추가
요청 시 토큰 소비
토큰 없으면 거부
┌─────────────┐
│ ○ ○ ○ ○ ○ │ ← 토큰 추가 (초당 10개)
│ Bucket │
└──────┬──────┘
↓ 요청당 1토큰 소비
[Request]
장점: 버스트 허용, 평균 속도 제한
구현: Redis + Lua Script
요청이 버킷에 쌓임
일정 속도로 처리
버킷 넘치면 거부
[Request]
↓
┌─────────────┐
│ ░ ░ ░ ░ ░ │ ← 큐 (고정 크기)
└──────┬──────┘
↓ 일정 속도로 처리
[Processed]
장점: 일정한 출력 속도
단점: 버스트 불가
고정 시간 창에서 요청 수 제한
|----60초----|----60초----|
| 100 요청 | 100 요청 |
|____________|____________|
단점: 경계에서 2배 버스트 가능
(59초에 100개 + 61초에 100개)
각 요청의 타임스탬프 기록
윈도우 내 요청 수 계산
현재 시간: 10:05:30
윈도우: 60초
[10:04:31, 10:04:45, 10:05:10, 10:05:25]
→ 윈도우 내 4개 요청
장점: 정확함
단점: 메모리 사용 많음
이전 윈도우와 현재 윈도우 가중 평균
이전 윈도우 (70개) × 30% + 현재 윈도우 (50개) × 70%
= 21 + 35 = 56개
장점: 메모리 효율적, 상당히 정확
-- rate_limit.lua
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local bucket = redis.call('HMGET', key, 'tokens', 'last_update')
local tokens = tonumber(bucket[1]) or limit
local last_update = tonumber(bucket[2]) or now
-- 토큰 리필
local elapsed = now - last_update
local refill = elapsed * (limit / window)
tokens = math.min(limit, tokens + refill)
if tokens >= 1 then
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'last_update', now)
redis.call('EXPIRE', key, window)
return {1, tokens} -- 허용, 남은 토큰
else
return {0, 0} -- 거부
end
const Redis = require('ioredis');
const redis = new Redis();
const rateLimitScript = fs.readFileSync('rate_limit.lua', 'utf8');
async function rateLimit(options) {
const { key, limit, window } = options;
return async (req, res, next) => {
const identifier = req.ip; // 또는 req.user.id
const redisKey = `ratelimit:${key}:${identifier}`;
const [allowed, remaining] = await redis.eval(
rateLimitScript,
1,
redisKey,
limit,
window,
Date.now() / 1000
);
res.set('X-RateLimit-Limit', limit);
res.set('X-RateLimit-Remaining', remaining);
if (!allowed) {
res.set('Retry-After', window);
return res.status(429).json({
error: 'Too Many Requests',
retryAfter: window,
});
}
next();
};
}
// 사용
app.use('/api/', rateLimit({ key: 'api', limit: 100, window: 60 }));
app.use('/api/search', rateLimit({ key: 'search', limit: 10, window: 60 }));
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const limiter = rateLimit({
store: new RedisStore({
client: redis,
prefix: 'rl:',
}),
windowMs: 60 * 1000, // 1분
max: 100, // 100 요청
message: { error: 'Too many requests' },
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
const limits = {
global: { limit: 10000, window: 60 }, // 전체 API
authenticated: { limit: 1000, window: 60 }, // 인증된 사용자
anonymous: { limit: 100, window: 60 }, // 익명 사용자
endpoint: { // 엔드포인트별
'/api/search': { limit: 10, window: 60 },
'/api/upload': { limit: 5, window: 60 },
},
};
const tierLimits = {
free: { limit: 100, window: 3600 }, // 시간당 100
basic: { limit: 1000, window: 3600 }, // 시간당 1000
pro: { limit: 10000, window: 3600 }, // 시간당 10000
enterprise: { limit: 100000, window: 3600 },
};
function getRateLimit(user) {
return tierLimits[user.tier] || tierLimits.free;
}
// 부하에 따른 동적 조정
async function getDynamicLimit() {
const load = await getSystemLoad();
if (load > 0.9) return { limit: 50, window: 60 }; // 높은 부하
if (load > 0.7) return { limit: 75, window: 60 }; // 중간 부하
return { limit: 100, window: 60 }; // 정상
}
X-RateLimit-Limit: 100 # 최대 요청 수
X-RateLimit-Remaining: 45 # 남은 요청 수
X-RateLimit-Reset: 1640000000 # 리셋 시간 (Unix timestamp)
Retry-After: 30 # 재시도까지 초 (429 응답 시)
// 429 Too Many Requests
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"retryAfter": 30,
"limit": 100,
"remaining": 0,
"reset": 1640000000
}
}
// 모든 인스턴스가 같은 Redis 참조
const redis = new Redis.Cluster([
{ host: 'redis-1', port: 6379 },
{ host: 'redis-2', port: 6379 },
{ host: 'redis-3', port: 6379 },
]);
Strong Consistency: 모든 노드가 동일한 카운트 (느림)
Eventual Consistency: 일시적 불일치 허용 (빠름)
대부분의 레이트 리밋은 Eventual Consistency로 충분
약간의 초과 허용이 성능보다 덜 중요
## Rate Limit Design
### Strategy
- 알고리즘: Token Bucket
- 저장소: Redis
### Limits
| 대상 | 제한 | 윈도우 | 키 |
|------|------|--------|-----|
| Global | 10000 | 분 | IP |
| Auth User | 1000 | 분 | user_id |
| Search API | 10 | 분 | user_id |
### Implementation
```javascript
// 핵심 구현 코드
// 429 응답 예시
---
요청에 맞는 레이트 리밋 전략을 설계하세요.
testing
사용자 계획을 기존 도메인 모델에 대해 stress-test하는 인터뷰 세션. 용어를 날카롭게 다듬고, 결정이 굳어질 때마다 CONTEXT.md(도메인 어휘 사전)와 ADR을 인라인으로 갱신한다. 새 기능 요구사항 탐색은 `/brainstorm`을, 기존 도메인 모델·용어와의 정합성 점검은 이 스킬을 사용한다.
development
# Excel (XLSX) Spreadsheet Skill Claude Code supports comprehensive spreadsheet operations through the **xlsx** skill, enabling creation, editing, and analysis of Excel files (.xlsx, .xlsm, .csv, .tsv). ## Trigger - When user needs Excel spreadsheet creation or editing - Financial modeling or data analysis required - Spreadsheet formulas and calculations needed - Data import from CSV/TSV files ## Core Capabilities **Primary functions include:** - Creating new spreadsheets with formulas and f
tools
Generate structured implementation workflows from PRDs and feature requirements
development
실시간 통신 설계 가이드를 실행합니다.