마이크로서비스 아키텍처(MSA) 환경에서는 수많은 서비스가 동시에 동작하며, 클라이언트의 요청도 급격하게 증가할 수 있다. 모든 요청을 무작정 받아들이면, 서비스 전체에 과부하가 걸릴 수 있다. 이를 방지하기 위해 트래픽 제어(Traffic Control)가 필요하다.

 

API Gateway는 단순히 요청을 라우팅하는 역할에 그치지 않고, 서비스 보호, 부하 분산, 응답 속도 최적화, 비용 절감 등 다양한 트래픽 제어 기능을 수행한다.

 

트래픽 제어란?


트래픽 제어(Traffic Control)는 클라이언트로부터 오는 요청을 관리, 조절, 그리고 최적화하는 과정이다.

 

주요 목적

  • 서버 오버로드 방지
  • 서비스 안전성 확보
  • 효율적인 리소스 사용
  • 사용자 경험 향상

 

트래픽 제어의 중요성

항목 설명
서비스 가용성 유지 과도한 트래픽으로 인해 서버가 다운되는 상황 방지
성능 최적화 응답 시간을 단축하여 사용자 만족도 증가
비용 절감 클라우드 인프라 비용을 효율적으로 관리
보안 강화 DDoS 공격 등 악의적 요청 방어 기능

 


트래픽 제어 방법 및 작동 원리


1️⃣ Rate Limiting (요청 속도 제한)

특정 시간 동안 허용되는 요청의 수를 제한하여 과도한 요청을 방지

 

 

📌 작동 방식

  • 일정 시간 동안 사용자 또는 클라이언트가 보낼 수 있는 요청 수를 제한
  • 기준 예시: IP, API Key, 사요자 ID, 요청 검토 등

 

Spring에서의 구현 방식

  • 주로 Interceptor 또는 Filter에서 구현
  • 요청의 IP 또는 사용자 ID로 요청 수를 카운팅하여 제한

 

관련 라이브러리

  • Bucket4j: Java 기반 버킷 알고리즘 지원
  • Spring Cloud Gateway: API Gateway 수준의 트래픽 제어 필터 제공

 

Rate Limiting 알고리즘

알고리즘 설명 특징
Fixed Window 고정된 시간 단위로 요청 수 제한 간단하지만 경계 지점에서 급증 가능
Sliding Log 요청 시간을 로긍에 저장하여 윈도우 내 요청 수 확인 정확하지만 메모리 사용 큼
Sliding Window Counter 윈도우를 잘게 나누어 카운트, Fixed + Log 결합 정확도와 효율성의 균형
Token Bucket 일정 속도로 토큰을 발행, 요청 시 토큰 소비 유연한 속도 제어 가능
Leaky Bucket 정해진 속도로 요청 처리, FIFO 큐 방식 일정한 처리율 유지

 

 

✔️ 구현 예시: Rate Limiting - Bucket4j

@Bean
public Filter rateLimitFilter() {
    return (request, response, chain) -> {
        Bucket bucket = Bucket4j.builder()
            .addLimit(Bandwidth.classic(10, Refill.greedy(10, Duration.ofSeconds(1))))
            .build();

        if (bucket.tryConsume(1)) {
            chain.doFilter(request, response);
        } else {
            response.setStatus(429);
            response.getWriter().write("Rate limit exceeded");
        }
    };
}
  • 초당 10건 요청 허용
  • 제한 초과 시 429 상태 코드 반환

 

✔️ 구현 예시: Rate Limiting - Spring Cloud Gateway

application.yml 설정

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: http://localhost:8081
          predicates:
            - Path=/api/user/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 5
                redis-rate-limiter.burstCapacity: 10
                key-resolver: '#{@ipKeyResolver}'
  • replenishRate: 초당 몇 개 요청 허용
  • burstCapacity: 버스트 상황에서 허용할 최대 요청 수

 

Key Resolver 설정

@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(
        exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
    );
}
  • 사용자 A는 1초에 5개의 요청만 가능하며, 초과 시 429 Too Many Requests 응답 반환

 

2️⃣ Throttling (스로틀링)

서버의 부하가 증가할 때 요청 처리 속도를 자동으로 조절하여 서버가 과부하 상태에 이르는 것을 방지

 

 

📌 작동 방식

  • 서버의 부하 상태에 따라 요청 처리 속도를 동적으로 조절
  • 주로 서비스 단 또는 컨트롤러 레벨에서 구현

 

관련 라이브러리

  • Resilience4j: CircuitBreaker, Retry, RateLimiter 등 다양한 기능 제공

 

내부 처리 순서

  1. 부하 감지 (CPU, Memory, Thread 수 등)
  2. 과부하 상태 진입 시 요청을 지연 처리하거나 차단
  3. 부하 감소 시 정상 상태 복귀

 

Rate Limiting과의 차이

항목 Rate Limiting Throttling
초점 요청 "" 제한 요청 "속도" 조절
기준 사용자/엔드포인트 중심 서버 상태 기반
특징 정량적 제한 동적, 상태 기반 제어

 

✔️ 구현 예시: Resilience4j Throttling 설정

@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
    return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
        .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(4)).build())
        .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
        .build());
}
  • CircuitBreaker와 TimeLimter 설정을 통해 요청을 제한

 

3️⃣ Load Balancing (부하 분산)

들어오는 트래픽을 여러 서버에 분산시켜 처리능력을 극대화하고 단일 실패 지점 제거

 

 

📌 작동 방식

  • 다수의 서버 인스턴스에 요청을 균등하게 분산하여 단일 지점 장애 방지

 

관련 라이브러리

  • Spring Cloud LoadBalancer: Spring Cloud 기반 로드 밸런싱

 

처리 순서

  1. 요청 수신
  2. 상태 확인 (Health Check)
  3. 로드 밸런싱 알고리즘 선택 (Round Robin, Least Connection 등)
  4. 요청 전달

 

API Gateway 연동 예

  • Spring Cloud Gateway + Eureka + Ribbon 조합
  • Kubernetes Ingress + Service + Endpoint 연동

 

✔️ 구현 예시: Spring Cloud LoadBalancer

application.yml 설정 (Ribbon 제거)

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false

 

WebClient 설정

@LoadBalanced
@Bean
public WebClient.Builder loadBalancedWebClientBuilder() {
    return WebClient.builder();
}
  • Eureka를 통해 서비스 인스턴스를 탐색하고 로드밸런싱 처리

 

4️⃣ Caching (응답 캐싱)

자주 요청되는 데이터를 임시로 저장하여 빠르게 응답할 수 있게 함

 

 

📌 작동 방식

  1. 최초 요청 -> 백엔드 서비스에서 응답
  2. 응답을 메모리/디스크 캐시에 저장
  3. 동일 요청 재발생 시 캐시에서 즉시 응답

 

💡 캐싱 효과

  • 서버 부하 감소
  • 응답 속도 향상
  • 중복 데이터 처리 최소화

 

예시 (Spring Gateway + Redis)

  • /products 응답 캐싱 60초 유지
filters:
  - name: AddResponseHeader
    args:
      name: Cache-Control
      value: max-age=60

 

🤔 실전 트래픽 제어 시 고려사항

항목 고려 내용
요청 유형 읽기 요청(Read) vs 쓰기 요청(Write)
사용자 유형 일반 유저 vs 프리미엄 유저
시간대 피크 타임(예: 점심시간) 대응
API 중요도 결제 API는 보다 엄격한 보호 필요
확장성 수평 확장을 고려한 아키텍처 구성