이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
공부 › 보안 › 웹 공격과 방어
요청 수 제한
초당 5건까지만 받는다는 것의 세 가지 의미
요청이 한꺼번에 몰리면 서버를 지키기 위해 일부를 거절합니다(429 Too Many Requests). "초당 5건"이라는 같은 제한도 세는 방법에 따라 통과하는 요청이 달라집니다.
개념 모형 · 널리 쓰이는 알고리즘 정의대로 만든 모형
이 실습에 나오는 개념
- Rate Limiting
- 일정 시간 동안 허용하는 요청의 수를 제한하는 것이다. 특정 사용자나 클라이언트가 과도한 요청을 보내 시스템 전체에 영향을 주는 것을 막고, 시스템이 감당할 수 있는 범위에서만 요청을 받도록 한다. 제한을 넘은 요청에는 보통 429 상태 코드로 응답한다.
- HTTP 상태 코드
- 서버가 요청을 처리한 결과를 나타내는 세 자리 숫자다. 2xx는 성공, 3xx는 다른 위치로의 이동(리다이렉션), 4xx는 클라이언트의 요청에 문제가 있음, 5xx는 서버 쪽 오류를 뜻한다. 200(성공), 201(생성됨), 400(잘못된 요청), 401(인증 필요), 403(권한 없음), 404(없음), 500(서버 오류)이 자주 쓰인다.
- API 게이트웨이
- 클라이언트의 모든 요청을 가장 먼저 받아 알맞은 내부 서비스로 전달하는 단일 진입점이다. 인증, 요청 수 제한, 로깅 같은 공통 기능을 한곳에서 처리한다. 클라이언트는 내부 서비스의 구성과 주소를 알 필요가 없다.
이렇게 바꿔 보세요
- 처음 설정으로 — 고정 윈도. 경계를 사이에 두고 0.4초 안에 10건이 전부 통과합니다.
- 같은 요청을 슬라이딩 윈도로 — 어느 1초 구간을 잡아도 5건을 넘지 않습니다.
- 토큰 버킷에 순간 몰림 — 모아 둔 토큰만큼은 한 번에 통과시킵니다.
- 고르게 초당 8건 — 초과분 3건씩이 거절됩니다.
- 토큰 버킷에 고른 요청 — 채워지는 속도만큼 꾸준히 통과합니다.
처음 설정으로 실행하면
- 0.80초에 요청 1: 0초대 카운터가 1입니다. 5 이하이므로 통과.
- 0.84초에 요청 2: 0초대 카운터가 2입니다. 5 이하이므로 통과.
- 0.88초에 요청 3: 0초대 카운터가 3입니다. 5 이하이므로 통과.
- 0.92초에 요청 4: 0초대 카운터가 4입니다. 5 이하이므로 통과.
- 0.96초에 요청 5: 0초대 카운터가 5입니다. 5 이하이므로 통과.
- 1.02초에 요청 6: 1초대 카운터가 1입니다. 5 이하이므로 통과.
- 1.06초에 요청 7: 1초대 카운터가 2입니다. 5 이하이므로 통과.
- 1.10초에 요청 8: 1초대 카운터가 3입니다. 5 이하이므로 통과.
- 1.14초에 요청 9: 1초대 카운터가 4입니다. 5 이하이므로 통과.
- 1.18초에 요청 10: 1초대 카운터가 5입니다. 5 이하이므로 통과.
- 2.20초에 요청 11: 2초대 카운터가 1입니다. 5 이하이므로 통과.
- 2.40초에 요청 12: 2초대 카운터가 2입니다. 5 이하이므로 통과.
- 2.60초에 요청 13: 2초대 카운터가 3입니다. 5 이하이므로 통과.
- 2.80초에 요청 14: 2초대 카운터가 4입니다. 5 이하이므로 통과.
실행 결과
- 고정 윈도는 정각마다 카운터가 0으로 돌아가므로, 경계 직전과 직후에 몰리면 짧은 시간에 제한의 두 배까지 통과합니다. 구현이 가장 단순하고 메모리도 적게 쓰는 대신 이런 틈이 있습니다.
- 거절할 때는 429 상태 코드와 함께 언제 다시 시도하면 되는지(Retry-After 헤더)를 알려 주는 것이 좋습니다. 서버가 여러 대면 카운터를 Redis 같은 공용 저장소에 둬야 제한이 서버 수만큼 늘어나지 않습니다.
코드
// 고정 윈도: 키 = 사용자 + 현재 초
String key = "rate:" + userId + ":" + (now / 1000);
long count = redis.incr(key); // 이번 초의 요청 수 +1
if (count == 1) redis.expire(key, 1); // 1초 뒤 사라짐
if (count > 5) return tooManyRequests(); // 429
이 모형의 전제
제한은 초당 5건으로 고정했습니다. 세 알고리즘의 동작은 널리 쓰이는 정의를 따랐습니다. 슬라이딩 윈도는 요청 시각을 모두 기록하는 방식(슬라이딩 윈도 로그)으로 구현했고, 토큰 버킷은 시간이 흐른 만큼 연속적으로 토큰이 채워진다고 보았습니다. 실제 서비스에서는 사용자나 IP, API 키 단위로 따로 셉니다.
앞 실습: 정보 누출 · 다음 실습: 의존성과 공급망