OpenAI API 속도 제한 처리와 재시도 로직 구현

문제 상황

ChatGPT API를 활용한 콘텐츠 생성 기능을 개발하던 중, 사용자가 몰리는 시간대에 429 Rate Limit 에러가 빈번하게 발생했다. 단순 재시도 로직으로는 부족했고, 제대로 된 에러 핸들링이 필요했다.

해결 방법

exponential backoff 전략을 적용한 재시도 로직을 구현했다.

const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

async function callOpenAI(prompt: string, retries = 3): Promise<string> {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await openai.createChatCompletion({
        model: 'gpt-3.5-turbo',
        messages: [{ role: 'user', content: prompt }],
      });
      return response.data.choices[0].message.content;
    } catch (error: any) {
      if (error.response?.status === 429) {
        const waitTime = Math.pow(2, i) * 1000;
        console.log(`Rate limited. Waiting ${waitTime}ms...`);
        await delay(waitTime);
        continue;
      }
      throw error;
    }
  }
  throw new Error('Max retries exceeded');
}

추가 개선

API 호출량을 줄이기 위해 Redis 캐싱도 함께 적용했다. 동일한 프롬프트에 대해서는 캐시된 응답을 반환하도록 하여 비용과 속도 모두 개선되었다.

const cacheKey = `openai:${hash(prompt)}`;
const cached = await redis.get(cacheKey);
if (cached) return cached;

const result = await callOpenAI(prompt);
await redis.setex(cacheKey, 3600, result);
return result;

결과

재시도 로직과 캐싱 적용 후 에러율이 95% 감소했고, API 비용도 약 40% 절감되었다. 프로덕션 환경에서 안정적으로 운영 중이다.