본문 바로가기

기술서적으로 배우는 기술

가상 면접 사례로 배우는 대규모 시스템 설계 기초 (feat. 4장 처리율 제한 장치의 설계)

들어가기 앞서

이전 1장 포스트을 보고 오신 분들은 갑자기 4장으로 이어져서 당황스러울 수도 있습니다. 2장, 3장에 내용은 "면접관에게 질문을 통해서 궁금증을 해소 하라"와 같은 시스템 설계 면접에 대한 부분이라 따로 정리하지 않았습니다. 해당 부분은 추후 기회가 된다면 정리할 예정입니다. 2장, 3장 내용이 궁금하신 분들은 책을 한 번 읽어 보는 것을 추천 드립니다. 

 

https://www.yes24.com/Product/Goods/102819435

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 - 예스24

“페이스북의 뉴스 피드나 메신저, 유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?”IT 경력자라도 느닷없이 대규모 시스템을 설계하려고 하면 막막하다고 느낄 수 있다. 특히나

www.yes24.com

 


처리율 제한 장치 설계

처리율 제한 장치는 클라이언트가 보내는 트래픽의 처리율을 제어하여 서버 리소스를 보호하고, 불필요한 요청을 제한하는 기능을 제공합니다. 이는 특정 기간 내 클라이언트 요청 횟수를 제한하는 데 사용됩니다.

 

예시

  1. 사용 제한: 사용자는 초당 2회 이상 글을 올릴 수 없다.
  2. 계정 생성 제한: 같은 IP 주소로는 하루에 10개 이상의 계정을 생성할 수 없다.
  3. 리워드 요청 제한: 같은 디바이스로는 주당 5회 이상 리워드를 요청할 수 없다.

 

장점

  1. 리소스 보호:
    • DOS 공격에 의한 자원 고갈을 방지.
    • 일정 허용 횟수를 초과하는 요청은 차단하여 서버 안정성 유지.
  2. 비용 절감:
    • 서드 파티 API 호출 비용 절감.
    • 불필요한 API 요청 제한으로 운영 효율성 증대.
  3. 서버 안정화:
    • 봇 트래픽 및 비정상적인 사용 패턴 필터링.
    • 서버 과부하 방지 및 서비스 품질 유지.

1단계: 문제 이해 및 설계 범위 확장

처리율 제한 장치는 클라이언트 요청을 관리하고 서버의 안정성을 보장하기 위해 설계됩니다. 이 장치는 요청 처리량을 제한하는 알고리즘을 기반으로 구현되며, 대규모 트래픽과 분산 환경에서도 유연하고 효율적으로 동작할 수 있어야 합니다.

 

처리율 제한 장치의 주요 특징 및 고려사항

  1. 구현 위치
    • 클라이언트 측: 요청을 제한하여 서버 부하를 줄일 수 있지만, 클라이언트는 위변조 가능성이 있어 신뢰성이 낮음.
    • 서버 측: 더 신뢰할 수 있으며, 제한 기준을 서버에서 통제할 수 있어 보안성과 일관성이 높음.
  2. 제한 기준의 유연성
    • 사용자 ID, IP 주소, 디바이스 ID 등 다양한 기준으로 요청을 제한할 수 있어야 합니다.
    • 시스템 설계 시 이러한 기준을 자유롭게 조합하고 설정할 수 있는 유연한 구조를 제공해야 합니다.
  3. 설계 확장성
    • 독립된 서비스로 구현: 중앙에서 제한 로직을 관리할 수 있음.
    • 애플리케이션 내부에 포함: 서비스별로 개별적인 처리율 제한 설정 가능.
    • 대규모 트래픽 및 분산 환경에서도 효율적으로 동작할 수 있도록 설계해야 함.
  4. 사용자 응답 처리
    • 요청이 제한된 경우, 사용자에게 명확히 알릴 수 있어야 하며, 일반적으로 **HTTP 상태 코드 429(Too Many Requests)**를 반환합니다.

 

처리율 제한 장치 설계 시 요구사항

  1. 정확한 요청 제한
    설정된 처리율을 초과하는 요청을 정확히 식별하고 제한해야 합니다.
  2. 낮은 응답시간
    처리율 제한 장치가 HTTP 응답시간에 부정적인 영향을 주지 않도록 설계해야 합니다. 처리율 제한 로직은 가볍고 빠르게 동작해야 합니다.
  3. 메모리 효율성
    가능한 적은 메모리를 사용하면서도 높은 성능을 유지할 수 있는 구조가 필요합니다.
  4. 분산형 처리율 제한
    하나의 처리율 제한 장치가 여러 서버나 프로세스에서 공유되며, 중앙에서 일관성 있는 요청 제한이 가능해야 합니다. 이를 위해 Redis와 같은 분산 캐시 시스템을 활용할 수 있습니다.
  5. 예외 처리
    요청이 제한되었을 때 사용자에게 명확히 알릴 수 있어야 하며, 이를 통해 사용자 경험을 저해하지 않아야 합니다.
  6. 높은 결함 감내성
    제한 장치에 장애가 발생하더라도 전체 시스템에 영향을 미치지 않도록 설계해야 합니다. 예를 들어, 처리율 제한 장치가 다운되더라도 서비스는 계속 작동할 수 있어야 합니다.

2단계 : 개략적 설계안 제시 및 동의 구하기

처리율 제한 장치를 설계할 때는 지나치게 복잡한 구조를 피하고, 기본적인 클라이언트-서버 통신 모델을 기반으로 단순하고 명확한 설계를 제안하는 것이 중요합니다. 이 단계에서는 처리율 제한 장치를 어디에 배치할지, 어떤 방식으로 구현할지를 논의합니다.

 

처리율 제한 장치는 어디에 둘 것인가?

처리율 제한 장치를 배치할 위치는 클라이언트와 서버 중 하나를 선택해야 합니다. 각 위치는 고유한 장점과 단점을 가지고 있으며, 서비스의 보안, 신뢰성, 확장성을 기준으로 선택이 이루어져야 합니다.

  1. 클라이언트 측에 구현
    클라이언트에서 처리율 제한을 구현하면 서버의 부하를 줄일 수 있고, 일부 트래픽을 클라이언트 단에서 분산 처리할 수 있다는 장점이 있습니다. 하지만 클라이언트는 위변조 가능성이 높고 신뢰성이 떨어진다는 치명적인 단점이 있습니다. 공격자가 제한 장치를 우회하거나 수정할 수 있는 여지가 있기 때문에 중요한 서비스에서는 적합하지 않습니다.
  2. 서버 측에 구현
    서버에서 처리율 제한을 관리하면 더 신뢰할 수 있고, 위변조의 위험 없이 요청을 정확히 제한할 수 있습니다.
    • 미들웨어 방식: 서버 측에서 처리율 제한 미들웨어를 구현하여, API 서버로 들어오는 요청을 사전에 필터링할 수 있습니다.
    • 제한된 요청은 HTTP 상태 코드 429(Too Many Requests)로 응답을 반환하여 사용자에게 요청 제한 사실을 알립니다.
    • 이 방식은 보안성과 신뢰성이 높은 만큼 대부분의 서비스에서 선호됩니다.

 

마이크로서비스 환경에서의 처리율 제한

마이크로서비스 아키텍처(MSA)에서는 API 게이트웨이가 처리율 제한 장치를 배치하는 일반적인 위치입니다. API 게이트웨이는 단순히 요청을 라우팅하는 역할을 넘어 다양한 기능을 제공합니다.

 

API 게이트웨이의 주요 기능:

  • 처리율 제한
  • SSL 종단 (SSL Termination)
  • 사용자 인증
  • IP 허용 및 차단 목록 관리

클라우드 서비스 제공업체(AWS, Azure, GCP 등)가 제공하는 완전 위탁관리형 API 게이트웨이를 사용하면, 처리율 제한을 포함한 여러 기능을 손쉽게 구현할 수 있습니다. 이를 통해 개발 및 유지보수 부담을 줄이고 안정성을 높일 수 있습니다.

만약 서비스가 이미 API 게이트웨이를 사용 중이라면, 처리율 제한 기능을 게이트웨이에 통합하는 것이 자연스럽고 효율적인 선택이 될 것입니다.

 

설계 시 고려해야 할 사항

  1. 기술 스택 검토
    • 현재 사용 중인 프로그래밍 언어와 캐시 서비스(예: Redis, Memcached 등)가 서버 측 처리율 제한 기능을 구현하기에 적합한지 확인합니다.
    • 예를 들어 Redis를 활용하면 분산 환경에서도 쉽게 처리율 제한 데이터를 공유할 수 있어 효율적입니다.
  2. 적합한 처리율 제한 알고리즘 선택
    • 비즈니스 요구사항에 따라 처리율 제한 알고리즘을 신중히 선택해야 합니다.
    • 주요 알고리즘:
      • Fixed Window Counter (고정 윈도우 카운터): 간단하고 빠르지만 초과 요청 처리에 약점이 있음.
      • Sliding Window Log (슬라이딩 윈도우 로그): 정확도는 높지만 메모리 소비가 큼.
      • Token Bucket (토큰 버킷): 유연성이 높아 다양한 비즈니스 요구를 충족할 수 있음.
      • Leaky Bucket (리키 버킷): 트래픽 스무딩 효과 제공.
  3. 클라우드 게이트웨이 활용 여부 검토
    • AWS API Gateway, Azure API Management, GCP API Gateway 등 클라우드 기반 API 게이트웨이를 활용하면 개발 부담을 줄이고 안정적인 기능을 사용할 수 있습니다.
  4. 분산 환경 지원
    • 여러 서버와 프로세스가 하나의 처리율 제한 데이터를 공유할 수 있는 구조를 고려해야 합니다.
    • Redis와 같은 분산 캐시 시스템을 활용하면 분산 환경에서도 효율적인 처리율 제한이 가능합니다.

 

 

 

개략적인 아키텍쳐

처리율 제한 장치는 요청량을 제어하기 위해 기본적으로 요청 카운터를 사용합니다. 요청이 처리될 때마다 카운터를 업데이트하며, 설정된 한도를 초과하면 추가 요청을 거부하는 방식으로 동작합니다. 이 카운터를 어디에 저장하고 관리할 것인지가 처리율 제한 장치 설계의 핵심입니다.

 

카운터 저장 위치의 고려사항

  1. 데이터베이스
    데이터베이스는 신뢰성이 높지만 접근 속도가 느리기 때문에 처리율 제한 장치의 요구사항에 적합하지 않습니다.
  2. 메모리 기반 캐시
    빠른 속도와 시간 기반 만료 정책을 지원하는 캐시는 처리율 제한 장치의 요구에 적합합니다. 대표적으로 Redis가 자주 사용됩니다.

 

Redis의 활용

Redis는 다음과 같은 명령어를 통해 처리율 제한 장치 구현을 간단하게 지원합니다.

  • INCR: 카운터 값을 1만큼 증가시킵니다.
  • EXPIRE: 카운터에 타임아웃을 설정하며, 설정된 시간이 지나면 카운터가 자동으로 삭제됩니다.

이 두 가지 명령어를 조합하면 처리율 제한 장치를 효율적으로 구현할 수 있습니다.

 

대략적인 동작 순서

  1. 클라이언트 요청
    클라이언트가 요청을 처리율 제한 미들웨어에 보냅니다.
  2. 레디스에서 카운터 확인
    처리율 제한 미들웨어는 Redis에서 해당 클라이언트의 카운터 값을 가져와 요청이 한도를 초과했는지 확인합니다.
    • 2-1. 요청 거부
      만약 카운터가 설정된 한도에 도달했다면, 요청을 거부하고 **HTTP 상태 코드 429(Too Many Requests)**로 응답합니다.
    • 2-2. 요청 허용
      카운터가 한도에 도달하지 않았다면, API 서버로 요청을 전달합니다. 이후 Redis에서 카운터 값을 1 증가시키고, 타임아웃이 설정되지 않은 경우 EXPIRE 명령어를 사용하여 만료 시간을 설정합니다.

 


3단계 : 상세 설계

처리율 제한 장치를 상세히 설계하기 위해서는 요청 초과 트래픽 처리 방식, 분산 환경에서의 구현 전략, 성능 최적화, 그리고 모니터링 방법을 명확히 이해해야 합니다. 이를 통해 시스템의 안정성과 확장성을 확보할 수 있습니다.

 

1. 처리율 한도 초과 트래픽의 처리

처리율 제한에 걸린 요청은 다음과 같은 방식으로 처리할 수 있습니다.

  1. HTTP 429 응답 반환
    요청이 제한에 걸리면 HTTP 429(Too Many Requests) 응답을 반환하여 클라이언트에 요청이 제한되었음을 알립니다.
  2. 메시지 큐 활용
    과부하로 인해 제한된 요청을 바로 거부하지 않고, 메시지 큐에 보관하여 나중에 처리하도록 할 수 있습니다.
    이는 주문 시스템과 같이 트래픽 폭증 시에도 데이터 손실을 방지할 수 있는 전략입니다.
  3. 처리율 제한 정보 제공
    클라이언트가 요청 제한 상태를 명확히 이해할 수 있도록 HTTP 응답 헤더에 처리율 제한 정보를 포함합니다.
    • X-Ratelimit-Remaining: 남은 처리 가능 요청 수.
    • X-Ratelimit-Limit: 허용된 최대 요청 수.
    • X-Ratelimit-After: 제한이 해제되는 시간(초).

 

2. 처리율 제한 장치의 동작 과정

  1. 처리율 제한 규칙 로드
    처리율 제한 규칙을 캐시(Redis), 설정 파일, 또는 application.yml에서 불러옵니다.
  2. 클라이언트 요청 도달
    클라이언트 요청은 서버에 도달하기 전에 처리율 제한 미들웨어를 거칩니다.
  3. 카운터 값 확인
    미들웨어는 Redis에서 클라이언트의 카운터 값을 가져와 요청이 제한에 걸렸는지 확인합니다.
    • 3-1. 요청 제한: 제한에 걸리면 메시지 큐에 저장하거나 429 응답을 반환합니다.
    • 3-2. 요청 허용: 제한에 걸리지 않으면 API 서버로 요청을 전달하고, Redis에서 카운터를 증가시킵니다.

 

3. 분산 환경에서의 처리율 제한 구현

  1. 경쟁 조건 해결
    동시성 이슈를 해결하기 위해 Redis의 Lua 스크립트 또는 정렬 집합(Sorted Set) 자료구조를 활용합니다.
    • Lua 스크립트는 원자성을 보장하며 성능 손실 없이 동시성 문제를 해결할 수 있습니다.
    • Sorted Set은 시간 기반 요청 관리에 유용합니다.
  2. 동기화 문제 해결
    여러 대의 처리율 제한 서버를 운영할 때는 중앙 집중형 데이터 저장소를 사용해 무상태(Stateless) 웹 계층을 만드는 것이 좋습니다.
    • Redis를 중앙 저장소로 활용하여 모든 서버가 동일한 데이터를 참조하도록 구성합니다.
    • 고정 세션 방식은 복잡성을 증가시키므로 권장하지 않습니다.

 

4. 성능 최적화

  1. 다중 데이터 센터 환경
    다중 데이터 센터에서의 지연시간(Latency)을 줄이기 위해 클라우드 서비스(예: Cloudflare)를 활용할 수 있습니다.
    • 클라우드 에지 서버를 통해 사용자와 가장 가까운 서버에서 요청을 처리하여 성능을 최적화합니다.
  2. 최종 일관성 모델 사용
    분산 환경에서 데이터 동기화를 위해 최종 일관성(Eventual Consistency) 모델을 사용하는 것이 적합합니다. 이는 성능과 확장성을 모두 만족시킬 수 있는 접근법입니다.

 

5. 모니터링

처리율 제한 장치의 효과적인 동작 여부를 확인하기 위해 지속적인 모니터링이 필요합니다.

  1. 규칙 최적화
    처리율 제한 규칙이 너무 엄격하면 유효 요청이 차단되고, 반대로 너무 느슨하면 제한의 효과가 감소합니다.
    이벤트 트래픽 급증 시 장치가 비효율적으로 동작하지 않도록 모니터링 데이터를 기반으로 규칙을 조정해야 합니다.
  2. 알고리즘 개선
    실시간 데이터 분석을 통해 처리율 제한 알고리즘의 효과성을 검증하고, 비즈니스 상황에 맞게 알고리즘을 수정합니다.

 


4단계: 마무리

처리율 제한 장치를 설계하고 구현한 후, 시스템을 더욱 고도화하고 효율적으로 운영하기 위해 추가적으로 고려할 수 있는 사항들을 정리합니다. 이러한 사항은 성능 향상, 다양한 환경에 대한 적응, 그리고 클라이언트 경험을 개선하는 데 도움을 줄 수 있습니다.

 

1. 경성 및 연성 처리율 제한

처리율 제한을 적용할 때, 트래픽 관리의 엄격성을 설정하는 방식에 따라 경성연성 처리율 제한으로 나눌 수 있습니다.

  • 경성 처리율 제한
    요청 개수가 설정된 임계치를 절대 초과하지 못하게 합니다.
    예: 중요한 금융 거래 API에서는 경성 처리율 제한을 적용하여 보안과 안정성을 보장합니다.
  • 연성 처리율 제한
    요청 개수가 일시적으로 임계치를 초과할 수 있지만, 일정 시간이 지나면 다시 정상화됩니다.
    예: 비즈니스 운영에서 트래픽 급증이 예상되는 이벤트성 트래픽에 적합합니다.

 

2. 다양한 계층에서의 처리율 제한

현재까지의 설계는 애플리케이션 계층에서 처리율 제한을 적용하는 방법을 중심으로 설명되었습니다. 그러나 시스템 요구사항에 따라 다양한 계층에서 처리율 제한을 적용할 수 있습니다.

  • 애플리케이션 계층
    사용자 ID, 디바이스 ID 등을 기준으로 요청을 제한합니다. 이 방식은 사용자 단위의 세밀한 제어가 가능합니다.
  • 네트워크 계층(3계층)
    IP 주소를 기준으로 처리율 제한을 적용합니다. 이를 통해 애플리케이션 계층에 도달하기 전에 봇이나 악성 트래픽을 차단할 수 있습니다.
    예: 방화벽 또는 CDN(예: Cloudflare)에서 IP 기반 제한 적용.

 

3. 처리율 제한 회피 방안

클라이언트가 처리율 제한에 걸리지 않도록 시스템 설계 단계에서 클라이언트 측에서도 몇 가지 개선 방안을 적용할 수 있습니다.

  1. 캐시 활용
    • 클라이언트 측에서 캐시를 사용하여 동일한 데이터를 반복적으로 요청하지 않도록 합니다.
    • 예: 자주 변하지 않는 데이터를 API 호출 대신 클라이언트 캐시에 저장.
  2. 임계치 이해
    • 클라이언트가 처리율 제한의 임계치를 이해하고, 짧은 시간에 너무 많은 요청을 보내지 않도록 설계합니다.
  3. 백오프 로직 구현
    • 재시도 로직을 구현할 때 충분한 백오프(backoff) 시간을 두어 제한에 걸리지 않도록 합니다.
    • 예: 재시도 횟수가 늘어날수록 대기 시간을 점진적으로 증가시키는 지수 백오프(exponential backoff) 적용.
  4. 예외 및 에러 처리
    • 클라이언트가 429 상태 코드를 우아하게 처리하도록 설계합니다.
    • 예: 에러 메시지를 사용자에게 명확히 전달하거나, 실패한 요청을 일정 시간 이후 자동으로 재시도.