Skip to content

[WIP] Remove retry logic and return 429 status immediately#5

Merged
redsunjin merged 1 commit intomainfrom
copilot/remove-retry-logic-in-chat-api-again
Mar 6, 2026
Merged

[WIP] Remove retry logic and return 429 status immediately#5
redsunjin merged 1 commit intomainfrom
copilot/remove-retry-logic-in-chat-api-again

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

  • Explore repository structure and understand current code
  • Update api/chat.js: remove retry logic, replace with single request, handle 429 immediately
  • Update index.html: add GitHub Pages → Vercel redirect at top of <head>
  • Update index.html: replace handleInquiryStep to remove retry loop and add 429-specific message
Original prompt

수정 사항 2가지

1. api/chat.js - 재시도 로직 완전 제거, 429 즉시 반환

기존 callGeminiWithRetry 함수(3번 재시도)를 완전히 제거하고, 단순 단일 요청으로 교체합니다.
429 에러는 재시도 없이 즉시 클라이언트에 429 상태코드로 반환합니다.

// api/chat.js - Vercel Serverless Function
//
// ⚠️ Vercel 환경변수 설정 필요:
// GEMINI_API_KEY: Google AI Studio (https://aistudio.google.com/app/apikey)

const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';

const SYSTEM_INSTRUCTION = `당신은 Gov-Tech AI 에이전시 '라이트닝(Lightning)'의 전문 AI 컨설턴트입니다. 사용자(공공기관/대기업 담당자)가 프로젝트 아이디어나 요구사항을 말하면, 이를 '라이트닝'의 핵심 역량(전자정부프레임워크 준수, 72시간 내 프로토타이핑, 보안 규정 준수, 2주 내 런칭)을 바탕으로 분석하여 답변하세요. 답변은 전문적이고 신뢰감 있게 하되, 핵심 기술(AI, 모바일, 웹 익스텐션)을 어떻게 활용할지 구체적으로 제안하세요. 답변은 한국어로 작성하며, 중요한 키워드는 **굵게** 표시하세요. 너무 길지 않게 핵심 위주로 답변하세요. 사용자의 요구사항이 충분히 파악되었다고 판단되면(또는 3~4번의 대화 이후), 반드시 응답 마지막에 정확히 "[INQUIRY_COMPLETE]" 라는 태그를 포함하세요.`;

module.exports = async function handler(req, res) {
  res.setHeader('Access-Control-Allow-Origin', 'https://flashgta-github-io.vercel.app');
  res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

  if (req.method === 'OPTIONS') return res.status(200).end();
  if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' });

  const apiKey = process.env.GEMINI_API_KEY;
  if (!apiKey) return res.status(500).json({ error: 'GEMINI_API_KEY not configured' });

  const { contents } = req.body;
  if (!contents || !Array.isArray(contents)) return res.status(400).json({ error: 'Invalid request body' });

  try {
    const response = await fetch(`${GEMINI_API_URL}?key=${apiKey}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        contents,
        systemInstruction: { parts: [{ text: SYSTEM_INSTRUCTION }] }
      })
    });

    if (response.status === 429) {
      return res.status(429).json({ error: 'Too many requests. Please wait a moment.' });
    }

    if (!response.ok) {
      const errBody = await response.text();
      throw new Error(`HTTP ${response.status}: ${errBody}`);
    }

    const data = await response.json();
    return res.status(200).json({ text: data.candidates[0].content.parts[0].text });

  } catch (error) {
    console.error('Gemini API error:', error);
    return res.status(500).json({ error: 'Failed to get AI response' });
  }
};

2. index.html - 두 가지 수정

2-1. GitHub Pages → Vercel 자동 리다이렉트

<head> 태그 안 맨 위에 아래 코드 추가:

<meta http-equiv="refresh" content="0; url=https://flashgta-github-io.vercel.app">
<script>window.location.replace('https://flashgta-github-io.vercel.app');</script>

2-2. handleInquiryStep 함수 재시도 루프 제거 및 429 전용 메시지 추가

기존 while 루프(maxRetries=3) 코드를 아래와 같이 교체:

async function handleInquiryStep(text) {
    conversationHistory.push({ role: 'user', parts: [{ text }] });

    showTyping();

    let aiText = null;

    try {
        const response = await fetch('/api/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ contents: conversationHistory })
        });

        if (response.status === 429) {
            hideTyping();
            appendMessage('요청이 너무 많습니다. 잠시 후 다시 시도해주세요. 🙏', 'ai');
            conversationHistory.pop();
            return;
        }

        if (!response.ok) throw new Error(`HTTP ${response.status}`);

        const data = await response.json();
        aiText = data.text;

    } catch (err) {
        hideTyping();
        appendMessage('현재 AI 응답이 지연되고 있습니다. 잠시 후 다시 시도해주세요.', 'ai');
        conversationHistory.pop();
        return;
    }

    hideTyping();

    const cleanText = aiText.replace(/\[INQUIRY_COMPLETE\]/g, '').trim();
    appendMessage(cleanText, 'ai');
    displayHistory.push({ role: 'ai', text: cleanText });
    conversationHistory.push({ role: 'model', parts: [{ text: aiText }] });

    if (inquirySummary === '' && conversationHistory.length >= 1) {
        inquirySummary = conversationHistory[0].parts[0].text;
    }

    if (aiText.includes('[INQUIRY_COMPLETE]')) {
        step = 'privacy';
        setTimeout(() => {
            const privacyMsg = '상담 내용을 담당자에게 전달하기 위해 연락처를 수집합니다.\n수집된 정보는 상담 목적으로만 사용되며, 응대 완료 후 즉시 파기됩니다.\n개인정보 수집에 동의하시겠습니까? (예 / 아니오)';
            appendMessage(privacyMsg, 'ai');
        }, 500);
    }
}

기대 효과

  • https://flashgta.github.io 접속 시 https://flashgta-github-io.vercel.app 으로 자동 리다이렉트
  • Gemini API 429 에러 발생 시 재시도 없이 즉시 사용자에게 친절한 안내 메시지 표시
  • Gemini API 요청 횟수 대폭 감소

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel
Copy link

vercel bot commented Mar 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flashgta-github-io Ready Ready Preview, Comment Mar 6, 2026 4:47pm

@redsunjin redsunjin marked this pull request as ready for review March 6, 2026 16:47
@redsunjin redsunjin merged commit b0ea128 into main Mar 6, 2026
2 of 3 checks passed
Copilot stopped work on behalf of redsunjin due to an error March 6, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants