API를 사용하다 보면 요청 횟수 제한에 걸려 429 에러를 마주하게 됩니다. 이런 상황을 효과적으로 처리하는 방법들을 알아보겠습니다.
function apiRequest($url) {
$maxRetries = 3;
$delay = 1;
for ($i = 0; $i < $maxRetries; $i++) {
$response = file_get_contents($url);
if ($response !== false) {
return $response;
}
sleep($delay);
$delay *= 2; // 지수 백오프
}
throw new Exception('API 요청 실패');
}
function handleApiCall($url) {
$context = stream_context_create([
'http' => ['ignore_errors' => true]
]);
$response = file_get_contents($url, false, $context);
$statusCode = explode(' ', $http_response_header[0])[1];
if ($statusCode == 429) {
sleep(60); // 1분 대기
return file_get_contents($url);
}
return $response;
}
function smartApiRequest($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
// X-RateLimit-Remaining 헤더 확인
if (preg_match('/X-RateLimit-Remaining: (\d+)/', $headers, $matches)) {
if ($matches[1] < 5) {
sleep(10); // 남은 요청이 적으면 대기
}
}
curl_close($ch);
return substr($response, $headerSize);
}
class RequestThrottler {
private $lastRequest = 0;
private $minInterval = 1; // 1초 간격
public function throttledRequest($url) {
$elapsed = time() - $this->lastRequest;
if ($elapsed < $this->minInterval) {
sleep($this->minInterval - $elapsed);
}
$this->lastRequest = time();
return file_get_contents($url);
}
}
function processBatch($urls, $batchSize = 10) {
$chunks = array_chunk($urls, $batchSize);
$results = [];
foreach ($chunks as $chunk) {
foreach ($chunk as $url) {
$results[] = file_get_contents($url);
}
// 배치 간 대기
sleep(5);
}
return $results;
}
function checkRateLimit($apiKey) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "rate_limit:$apiKey";
$current = $redis->get($key);
if ($current >= 100) { // 시간당 100회 제한
return false;
}
$redis->incr($key);
$redis->expire($key, 3600); // 1시간
return true;
}
class ApiQueue {
private $queue = [];
public function addRequest($url, $priority = 1) {
$this->queue[] = ['url' => $url, 'priority' => $priority];
usort($this->queue, fn($a, $b) => $b['priority'] - $a['priority']);
}
public function processQueue() {
while (!empty($this->queue)) {
$request = array_shift($this->queue);
file_get_contents($request['url']);
sleep(1);
}
}
}
이러한 방법들을 조합하여 사용하면 API Rate Limit 문제를 효과적으로 해결할 수 있습니다. 특히 실제 서비스에서는 Redis나 데이터베이스를 활용한 요청 추적이 가장 안정적입니다.