[개발] 프로그램 지식

[server] 429 Too Many Requests 에러란? 원인 및 해결방법

  • -
반응형

429 Too Many Requests: 원인과 해결 방법

429 Too Many Requests는 클라이언트가 일정 시간 동안 너무 많은 요청을 보냈을 때 서버가 반환하는 HTTP 상태 코드입니다. 주로 API 호출 시 요청 제한(레이트 리미트, Rate Limit)을 초과했을 때 발생합니다.

  • 레이트 리미트 초과: 클라이언트가 서버의 요청 허용 한도를 초과.
  • 봇 트래픽: 자동화된 스크립트나 봇이 과도한 요청을 보냈을 때.
  • 서버 보호 메커니즘: DoS(서비스 거부 공격)를 방지하기 위한 서버 설정.

이 에러는 클라이언트의 요청이 차단되어 서버와의 통신이 중단될 수 있으며, 다음과 같은 부정적인 영향을 미칩니다:

  • 사용자 경험 저하: 서비스 응답이 느리거나 차단됨.
  • API 사용 제한: 클라이언트 애플리케이션의 기능이 제한됨.

API 요청 빈도를 줄여 서버가 설정한 한도를 초과하지 않도록 합니다. 예:

// JavaScript Fetch 예제 function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function fetchData() { for (let i = 0; i < 5; i++) { await fetch('https://example.com/api') .then(response => response.json()) .then(data => console.log(data)); await wait(1000); // 1초 대기 } } fetchData();

API 문서에서 요청 제한 정보를 확인하고, 클라이언트가 해당 한도를 준수하도록 구현합니다.

서버가 Retry-After 헤더를 반환하는 경우, 지정된 시간 후에 요청을 다시 시도합니다.

// JavaScript Fetch 예제 fetch('https://example.com/api') .then(response => { if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') || 1; // 기본값: 1초 console.log(`429 에러 발생. ${retryAfter}초 후 재시도합니다.`); setTimeout(() => fetch('https://example.com/api'), retryAfter * 1000); } });

동일한 데이터에 대한 반복 요청을 줄이기 위해 캐싱을 활용합니다.

// 간단한 캐싱 예제 let cache = {}; async function getData(url) { if (cache[url]) { return cache[url]; } const response = await fetch(url); const data = await response.json(); cache[url] = data; return data; }

한 프로젝트에서 여러 API 키를 사용하여 요청을 분산합니다(가능한 경우).

Python Flask에서 Rate Limit을 구현하는 예제:

from flask import Flask, request, jsonify from time import time app = Flask(__name__) requests_store = {} LIMIT = 5 # 허용 요청 수 TIME_WINDOW = 60 # 시간 제한 (초) @app.route('/api', methods=['GET']) def api(): client_ip = request.remote_addr now = time() if client_ip not in requests_store: requests_store[client_ip] = [] requests_store[client_ip] = [t for t in requests_store[client_ip] if now - t < TIME_WINDOW] if len(requests_store[client_ip]) < LIMIT: requests_store[client_ip].append(now) return jsonify({"message": "요청 성공"}) else: return jsonify({"error": "429 Too Many Requests"}), 429 if __name__ == '__main__': app.run(debug=True)
  • 403 Forbidden: 접근이 거부되었을 때.
  • 503 Service Unavailable: 서버가 요청을 처리할 준비가 되지 않았을 때.
  • 408 Request Timeout: 요청이 일정 시간 내에 완료되지 않았을 때.

반응형

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.