Develop

Node.js API Rate Limiting 완벽 가이드 — 요청 횟수 제한으로 서버를 보호하는 방법

DDoS 공격, 무차별 대입 크래킹, 스크랩 크롤러로부터 Node.js API 서버의 한정된 자원을 방어하기 위해 express-rate-limit 및 Redis 캐시 메모리 스토리지를 조합한 분산 처리량 제한 실무 구축안을 제시합니다.

Node.jsRate Limiting보안Express.jsbackend
Node.js Express 서버에서 Rate Limiting이 적용되어 429 Too Many Requests 응답을 반환하는 화면
  • ·Rate Limiting 없이 API를 공개하면 무차별 대입 공격, 크롤링, DDoS 공격에 노출될 수 있다
  • ·express-rate-limit은 기본적으로 메모리에 카운터를 저장하므로 서버가 여러 대면 인스턴스마다 별도로 카운트된다
  • ·Redis를 스토어로 쓰면 여러 서버 인스턴스가 카운터를 공유해 분산 환경에서도 정확한 Rate Limiting이 가능하다
  • ·429 Too Many Requests는 Rate Limit 초과를 나타내는 표준 HTTP 상태 코드다
예전에 신규 회원가입 시 SMS 인증번호를 발송하는 API를 열어두었다가, 밤새 인증 유효성 체크가 안 된 상태에서 어떤 공격자가 스크립트로 1초에 수십 번씩 SMS 발송 API를 무차별 공격해 들어온 적이 있습니다. 아침에 일어나 보니 수백만 원 상당의 인증 문자 발송 비용 폭탄이 쌓여있어 눈앞이 캄캄해졌죠. 그 직후 즉각 Rate Limiting 방어 메커니즘을 구축해 특정 IP와 계정 명의당 분당 요청 한계선을 그어두었습니다. 소를 잃고 나서야 고친 외양간이었지만, API 서버 보안 방벽에 횟수 제한이라는 빗장을 걸어 잠그는 것이 서비스 생존에 얼마나 중차대한 문제인지 뼈저리게 공부했습니다.

1. 남용 차단과 인메모리 카운터

Node.js API 남용을 막는 express-rate-limit 라이브러리 기본 셋업 요령

API 서버에 어떠한 진입 제어가 없다면 악의적인 봇이 무차별적으로 서버 CPU를 독점해 정당한 사용자들의 대기 시간이 한없이 늘어납니다. Express 기반 백엔드 아키텍처라면 express-rate-limit 모듈을 소환해 1차 저지선을 그어줄 수 있습니다. 이 라이브러리는 특정 시간 창(windowMs)과 해당 기간 진입을 허용할 최대 카운트(max) 빗장을 지정해 줍니다. 지정된 리밋을 초과해 무단 유입되는 패킷에 대해서는 가볍게 429 Too Many Requests HTTP 상태 에러 코드를 즉각 반환하여 후속 내부 DB 쿼리 연산이나 비즈니스 로직을 태우지 않고 원천 드롭시킵니다.

import rateLimit from 'express-rate-limit';

// 일반 API 제한
export const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15분
  max: 100,
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: '요청이 너무 많습니다. 잠시 후 다시 시도하세요.' },
});

// 로그인 API 엄격한 제한
export const loginLimiter = rateLimit({
  windowMs: 60 * 1000, // 1분
  max: 5,
  message: { error: '로그인 시도 횟수를 초과했습니다.' },
});

2. Redis 공유 스토어 분산 조율

Redis 캐시 메모리 스토리지를 연동해 다중 Node.js 분산 인스턴스에서 API 요청 제어하는 법

express-rate-limit의 기본 카운트 기록소는 Node 프로세스의 로컬 RAM 메모리 공간입니다. 로드밸런서가 가동되고 인스턴스가 3~4대로 병렬 수평 증설되는 프로덕션 배포 환경에서는, 유저 요청이 여러 인스턴스로 분산되어 각 장비마다 카운터가 제각각 쌓이는 모순이 일어납니다. 이 횟수 오차 구멍을 메우려면 인메모리 캐시 DB인 Redis 저장소를 중앙 카운팅 허브 스토어로 이식해야 합니다. rate-limit-redis 어댑터를 미들웨어 스토어에 연결해주면 모든 분산 Node 서버들이 단 하나의 실시간 Redis 카운트를 공유해 한 치의 오차도 없이 일관된 차단막을 유지해 줍니다.

3. 레이트 리미팅 보안 전략

Node.js API 보안을 위한 Rate Limiting 전략과 프록시 우회 방지 방법

Rate Limiting 전략은 단순히 일괄적으로 적용하기보단 라우터별로 다르게 가중치를 잡아야 합니다. 예를 들어 과중한 메일 전송 API나 회원가입 요청은 매우 엄격히 막고, 일반 메인 아티클 리스트 조회는 너그럽게 풀어두는 것이죠. 또한 사용자 인증 유무에 따라 로그인한 사용자는 ID로, 비로그인 방문자는 IP로 분리 제어해야 공정한 성능 트래픽 배포가 구현됩니다.

자주 묻는 질문

Proxy 서버(Nginx, Cloudflare 등)를 거쳐 백엔드 Node 서버로 올 때 클라이언트 IP가 127.0.0.1로 다 똑같이 묶여버려 다른 유저들까지 싸잡아 429 에러로 차단됩니다.+

리버스 프록시 장비가 패킷을 넘겨줄 때 실제 클라이언트의 진짜 IP는 X-Forwarded-For 헤더에 담겨서 들어옵니다. Express 설정 최상단에 app.set('trust proxy', 1) 구문을 반드시 기입해 두어 프레임워크가 로컬 프록시 IP가 아닌 헤더 속 실제 사용자의 공인 IP 주소를 식별해 차단 카운팅을 매기도록 바로잡아 주셔야 합니다.

특정 유료 VIP 회원이나 특정 내부 어드민 직원의 요청 횟수만 제한 예외 처리(Bypass)를 하려면 어떡해야 하나요?+

express-rate-limit 옵션 객체 안에 존재하는 skip 콜백 훅 메서드를 가동하면 됩니다. 해당 함수 인자로 넘어오는 req 객체의 인증 세션을 털어 헤더나 유저 식별 토큰에 특정 VIP 권한 서명이 증명된다면 true 값을 리턴하여 레이트 리미트 검문소를 가볍게 하이패스 통과하도록 조율해 둘 수 있습니다.

관련 글