PHP에서 API Rate Limit 초과 문제 해결하기

프리터코더·2025년 6월 6일
0

php 문제 해결

목록 보기
65/79

API를 사용하다 보면 요청 횟수 제한에 걸려 429 에러를 마주하게 됩니다. 이런 상황을 효과적으로 처리하는 방법들을 알아보겠습니다.

1. 기본적인 재시도 로직 구현

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 요청 실패');
}

2. HTTP 상태 코드 확인 후 처리

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;
}

3. cURL을 이용한 헤더 정보 활용

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);
}

4. 요청 간격 제어하기

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);
    }
}

5. 배치 처리로 요청 최적화

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;
}

6. Redis를 이용한 요청 카운터

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;
}

7. 우선순위 큐 구현

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나 데이터베이스를 활용한 요청 추적이 가장 안정적입니다.

profile
일용직 개발자. freetercoder@gmail.com

0개의 댓글