핵심 인사이트 (3줄 요약)

  1. 본질: Leaky Bucket (리키 버킷) 알고리즘은 입력 트래픽의 버스트(Burst) 여부와 무관하게 일정한 속도(Constant Rate) 로만 패킷을 출력하는 Traffic Shaping (트래픽 쉐이핑) 알고리즘이다 — 물이 구멍 뚫린 양동이에서 일정 속도로 새어나오는 것처럼.
  2. 가치: 네트워크 QoS (Quality of Service, 서비스 품질) 보장에 이상적이다 — 버스트 트래픽을 흡수하고, 다운스트림에는 예측 가능한 일정 속도로만 전달하여 버퍼 오버플로우와 혼잡을 방지한다.
  3. 판단 포인트: 리키 버킷은 "일정 출력 속도 보장(평활화)"이 목적 — 토큰 버킷은 "평균 속도 제한 + 버스트 허용"이 목적. 버스트를 허용할지, 완전히 평활화할지가 선택의 기준이다.

Ⅰ. 개요 및 필요성

네트워크나 API에서 트래픽 버스트가 발생하면:

  • 순간 과부하로 패킷 손실 증가
  • 큐잉 지연(Queuing Latency) 급증
  • 서비스 품질(QoS) 저하
  • 다운스트림 서버 과부하

실제 시나리오:

  • 뉴스 사이트에서 기사 발행 직후 트래픽 폭증 (1초에 10,000 요청)
  • 이벤트 큐에서 배치로 메시지가 쏟아질 때
  • IoT 센서가 데이터를 일시에 전송할 때
입력 (불규칙 버스트):
  ┌───────────────────────────────────────────────────┐
  │ 시각 | 요청 수                                     │
  │ 0s   | 1,000 (폭발적 버스트)                       │
  │ 1s   | 0                                          │
  │ 2s   | 500 (또 버스트)                             │
  └───────────────────────────────────────────────────┘

출력 (일정 속도):
  ┌───────────────────────────────────────────────────┐
  │ 시각 | 처리 수                                     │
  │ 0s   | 100 (버킷에서 일정 속도로 새어나옴)           │
  │ 1s   | 100                                        │
  │ 2s   | 100                                        │
  └───────────────────────────────────────────────────┘
  → 버스트가 버킷(큐)에 흡수되고 일정 속도로 처리
  → 버킷 넘치면(overflow) 초과 패킷/요청 드롭
  • 📢 섹션 요약 비유: 리키 버킷은 구멍 뚫린 양동이 — 폭우(버스트 트래픽)가 쏟아져도 양동이가 물을 받아두고, 구멍(출력)은 항상 일정한 속도로만 물(트래픽)을 내보낸다. 양동이가 넘치면 물(패킷)은 버려진다.

Ⅱ. 아키텍처 및 핵심 원리

┌────────────────────────────────────────────────────────────────┐
│                  Leaky Bucket Algorithm                        │
│                                                                │
│  입력 (불규칙 트래픽):                                           │
│  ▓▓▓▓▓▓▓▓▓ ──────────▶ ┌────────────────────┐                 │
│  ▓ 버스트 ▓              │   Bucket (큐/버퍼)  │                 │
│  ▓ 트래픽 ▓              │                    │  ← 버킷 초과     │
│  ▓▓▓▓▓▓▓▓▓              │  [요청][요청][요청] │    DROP          │
│                          │  [요청][요청][요청] │                 │
│  단순 트래픽:             │  capacity = B      │                 │
│  ▓ 정상 ▓  ─────────────▶│                    │                 │
│  ▓▓▓▓▓▓▓              └──────────┬───────────┘                 │
│                                  │                             │
│                          일정 속도 R req/s                      │
│                                  │                             │
│                                  ▼                             │
│                         ┌─────────────────┐                    │
│                         │ 다운스트림 서버   │                    │
│                         │ (일정 부하 보장) │                    │
│                         └─────────────────┘                    │
└────────────────────────────────────────────────────────────────┘
class LeakyBucket:
    def __init__(self, rate: float, capacity: int):
        self.rate = rate          # 처리 속도 (요청/초)
        self.capacity = capacity  # 버킷 크기 (최대 대기 요청 수)
        self.queue = deque()      # 대기 큐
        self.last_leak = time.time()

    def add_request(self, request) -> bool:
        self._leak()  # 현재 시각까지 처리 가능한 요청 처리
        if len(self.queue) < self.capacity:
            self.queue.append(request)
            return True           # 큐에 추가 성공
        else:
            return False          # 버킷 가득 참 → DROP

    def _leak(self):
        now = time.time()
        elapsed = now - self.last_leak
        leaked = int(elapsed * self.rate)  # 처리할 수 있는 요청 수
        for _ in range(min(leaked, len(self.queue))):
            process(self.queue.popleft())  # 일정 속도로 처리
        self.last_leak = now
네트워크 QoS 계층:
  1. Traffic Classification (분류)
  2. Traffic Policing (토큰 버킷/리키 버킷으로 초과 트래픽 드롭)
  3. Traffic Shaping  ← 리키 버킷 활용 (버스트 평활화 후 전달)
  4. Scheduling (우선순위 큐 기반 처리)

리키 버킷의 QoS 역할:
  CBR (Constant Bit Rate, 일정 비트율) 보장 → 음성/영상 스트리밍
  버스트 제거 → 혼잡(Congestion) 방지
항목설명포인트
핵심 역할입력·상태·출력을 분리하는 책임 경계구현보다 경계를 먼저 본다.
제어 지점조건, 이벤트, 정책이 만나는 곳병목과 결합이 생기는 곳이다.
검증 포인트테스트·로그·모니터링으로 확인할 지점운영 가능성이 설계 품질을 결정한다.
  • 📢 섹션 요약 비유: 리키 버킷은 도로의 신호등 — 아무리 많은 차(버스트 트래픽)가 몰려도 신호등(리키 버킷)이 일정 간격으로만 차를 통과시켜서 교차로(다운스트림) 혼잡을 방지한다.

Ⅲ. 비교 및 연결

비교 항목Token Bucket (토큰 버킷)Leaky Bucket (리키 버킷)
목적평균 속도 제한 + 버스트 허용일정 출력 속도 보장 (평활화)
버스트 트래픽 처리버킷에 토큰 있으면 즉시 처리버킷(큐)에 흡수, 일정 속도 출력
버킷 가득 찰 때추가 토큰 무시 (요청 거부)패킷/요청 드롭
출력 속도가변 (버스트 시 높음)고정 (항상 R req/s)
적합한 사용처API Rate Limiting네트워크 QoS, 트래픽 쉐이핑
알고리즘 복잡도중간단순 (큐 기반)
알고리즘버스트 처리메모리정확도적합한 사용처
Fixed Window경계에서 2× 버스트 가능O(1)낮음단순 카운터
Sliding Window Log없음 (정확)O(N)높음정밀 제어
Sliding Window Counter근사 제거O(1)높음대부분 상황
Token Bucket허용 (B 용량까지)O(1)높음API Gateway
Leaky Bucket흡수 후 평활화O(B)높음네트워크 QoS
  • 📢 섹션 요약 비유: 토큰 버킷과 리키 버킷의 차이는 고속버스 터미널(토큰 버킷)과 지하철(리키 버킷)의 차이 — 고속버스는 여러 버스가 한꺼번에 출발(버스트 허용)할 수 있지만, 지하철은 정해진 배차 간격(일정 속도)을 반드시 지킨다.

Ⅳ. 실무 적용 및 기술사 판단

# nginx의 limit_req는 리키 버킷 알고리즘 사용
http {
    # 리키 버킷 존 정의 (IP당 10 req/s, 메모리 10MB)
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

    server {
        location /api/ {
            # 버킷 크기=20 (최대 대기 요청)
            # nodelay: 버킷 내에서는 즉시 처리 (혼합 방식)
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend;
        }
    }
}

Nginx limit_reqburst 파라미터:

  • burst=20: 최대 20개 요청을 큐잉(리키 버킷의 버킷 크기)
  • nodelay: 큐잉된 요청을 즉시 처리 (토큰 버킷과 유사한 동작)
  • nodelay 없음: 큐잉된 요청을 rate에 맞춰 지연 처리 (순수 리키 버킷)
Kafka Consumer 속도 제어:
  Producer → Kafka Topic (버킷 역할)
            → Consumer (일정 속도 = max.poll.records + 처리 스레드 수)

  버킷 역할: Kafka Topic의 파티션
  누출 속도: Consumer의 처리 처리량 (rps)
  오버플로우: Retention 정책 (오래된 메시지 삭제)
요구사항선택 알고리즘이유
API Rate LimitingToken Bucket버스트 허용 + 평균 속도 제한
실시간 스트리밍 QoSLeaky BucketCBR 보장, 지터 최소화
메시지 처리 평활화Leaky Bucket배치 입력 → 일정 처리
CDN 대역폭 제한Token Bucket사용자별 버스트 허용
IoT 데이터 수집Leaky Bucket센서 폭발 데이터 평활화

판단 체크리스트

  1. 해결하려는 변화 축이 분명한가?
  2. 추상화 비용보다 변경 절감 효과가 큰가?
  3. 테스트·로그·운영 가시성이 확보되는가?
  4. 팀이 이 구조를 일관되게 유지할 수 있는가?
  • 📢 섹션 요약 비유: Nginx의 burst는 리키 버킷에 약간의 여유 공간 — 폭발적 요청이 와도 burst 크기만큼은 큐에 넣어두고 일정 속도로 처리한다. nodelay를 추가하면 버킷 내에서는 즉시 처리하는 하이브리드 방식이 된다.

Ⅴ. 기대효과 및 결론

리키 버킷 알고리즘은 "예측 가능한 출력"이 핵심 가치다:

기대효과:

  • 트래픽 평활화: 버스트 트래픽의 충격을 흡수하여 다운스트림 보호
  • CBR 보장: 일정 비트율로 음성/영상 스트리밍 품질 보장
  • 혼잡 방지: 네트워크 혼잡 제어의 기반 알고리즘
  • 단순한 구현: 큐 + 타이머만으로 구현 가능

한계:

  • 버스트 트래픽을 허용하지 않으므로 정상적인 접속 급증(프로모션 이벤트)에도 요청이 드롭될 수 있음
  • 큐잉으로 인한 지연(Queuing Delay) 발생
  • 토큰 버킷 대비 사용자 경험 저하 가능성

최종 선택 기준: 출력 속도의 일관성(평활화)이 중요하면 리키 버킷, 사용자 경험(버스트 허용)이 중요하면 토큰 버킷을 선택한다.

확장 방향은 ① 선언형 API와의 결합, ② 관측 가능성(Observability) 내장, ③ 분산 환경에 맞는 변형 패턴 적용이다.

  • 📢 섹션 요약 비유: 리키 버킷은 철도 시스템 — 아무리 많은 승객이 역에 몰려도 기차(출력)는 정해진 시간표(일정 속도)대로만 출발한다. 다음 기차 전까지 승객은 플랫폼(버킷)에서 대기하고, 플랫폼이 가득 차면 더 이상 입장할 수 없다(드롭).

📌 관련 개념 맵

관계개념설명
상위 개념Traffic Shaping (트래픽 쉐이핑)리키 버킷이 구현하는 QoS 기법
대비 알고리즘Token Bucket버스트 허용 + 평균 속도 제한 방식
연관 개념QoS (Quality of Service)리키 버킷이 보장하는 네트워크 품질
연관 개념CBR (Constant Bit Rate)리키 버킷이 실현하는 일정 비트율
구현체Nginx limit_req리키 버킷 기반 Rate Limiting
연관 개념Backpressure버킷 가득 찰 때의 역압 처리 전략
연관 알고리즘Sliding Window Counter다른 Rate Limiting 비교 알고리즘

📈 관련 키워드 및 발전 흐름도

queue shaping → 리키 버킷 트래픽 쉐이핑 → QoS 제어

👶 어린이를 위한 3줄 비유 설명

  1. 리키 버킷은 구멍 뚫린 물통 — 빗물(버스트 트래픽)이 아무리 많이 와도 물통(버킷)이 받아두고, 구멍(출력)에서는 항상 똑같은 속도로만 물이 나와.
  2. 물통이 가득 차면 더 이상 물을 받을 수 없어서 넘치는 빗물(초과 트래픽)은 버려져(드롭) — 토큰 버킷과 달리 버스트를 즉시 처리하지 않고 일정 속도로만 내보내.
  3. 이 방법은 네트워크에서 영상 통화(CBR)처럼 "일정한 속도"가 중요할 때 사용해 — 갑자기 데이터가 몰려도 수신자는 일정한 속도로만 받으니 화면이 끊기지 않아.