속도 제한은(는) 무엇을 하나요?
규칙
- API 엔드포인트에는 토큰 버킷, 인증/로그인 경로에는 슬라이딩 윈도우 사용
- 호출자는 API 키로 먼저 식별하고, 실패 시 IP로 대체 — 인증된 경로에서는 IP만 사용 금지
429 Too Many Requests 응답에 Retry-After 헤더(초)와 X-RateLimit-Remaining 헤더 포함
- 카운터는 Redis(또는 서버리스의 경우 Upstash)에 저장 — 다중 인스턴스 배포에서 인메모리 사용 금지
- 적절한 기본값 설정: 일반 API는 분당 100회, 인증은 분당 5회, 읽기는 분당 1000회
- 서버리스의 경우
@upstash/ratelimit 사용 — Redis 원자성과 슬라이딩 윈도우를 기본적으로 처리
- 미들웨어로 속도 제한 구현 — 전역 적용, 경로별로 더 엄격한 제한으로 재정의 가능
- Next.js: middleware.ts 또는 API 라우트 핸들러에서 속도 제한, React 컴포넌트에서는 금지
- 계층별 제한 분리: 무료, 프로, 엔터프라이즈 — 계층은 JWT 또는 데이터베이스 조회로 저장
- 호출자 식별과 함께 속도 제한 히트 로깅 — 남용 패턴 조기 발견
패턴
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, "10 s"),
analytics: true,
});
const { success, limit, remaining, reset } = await ratelimit.limit(identifier);
피해야 할 것
- 서버리스 또는 다중 인스턴스 설정에서 인메모리 속도 제한 — 호출 간 상태 손실
- 애플리케이션 레이어에서만 속도 제한 — CDN/엣지 제한도 추가(Cloudflare, Vercel)
- 과도하게 공격적인 제한으로 합법적인 사용자 차단 — 관대하게 시작하고 데이터 기반으로 강화
- 웹훅 및 공개 양식 제출에 대한 속도 제한 누락