Phase 4를 마무리하다 - 사용량 제한 두 겹 (Day 11)

도로의 이것저것·2026년 8월 4일

AI에이전트

목록 보기
11/15

어제 디스코드 봇으로 에이전트를 슬래시 커맨드까지 연결했으니, 오늘은 로드맵 Phase 4의 마지막 조각인 "무료 티어 방어"를 끝냈어요. 디스코드 봇에 사용량 캡을 걸고, 포트폴리오 사이트에도 같은 에이전트를 호출하는 챗 위젯을 넣었어요.

1. usage.py에 한도 체크 붙이기

usage.py는 원래 호출 횟수를 기록만 하고 있었어요. 여기에 오늘 몇 번 불렀는지 세고, 한도를 넘었는지 판단하는 함수 두 개를 추가했어요.

def get_today_count(kind: str = None) -> int:
    """오늘 호출 횟수. kind를 생략하면 generate+embed 합계."""
    ...

def is_over_limit(daily_limit: int, kind: str = None) -> bool:
    return get_today_count(kind) >= daily_limit

bot.py의 /review, /ask는 실행 직전에 이 함수로 체크해서, 한도를 넘으면 Gemini를 아예 호출하지 않고 "오늘 한도에 도달했어요" 메시지로 대신 응답해요.
오늘 사용량을 바로 확인할 수 있는 /usage커맨드도 추가했어요.

2. 포트폴리오 사이트에 챗 위젯 추가

로드맵에서부터 강조했던 부분이에요 — 포트폴리오 사이트가 "저와 대화해보세요" 데모를 가지려면, 새 로직을 짜는 대신 이미 만든 에이전트를 그대로 재사용해야 한다는 원칙. kodex-code-review-agent/ask.py의 RAG 로직(질문 임베딩 → 벨로그 글 검색 → 근거 기반 답변)을 TypeScript로 그대로 옮겨서 Next.js API 라우트(/api/kodex-chat)로 만들었어요. 시스템 프롬프트, 모델, 유사도 기준까지 파이썬 버전과 동일해요.

화면에는 오른쪽 아래 "Kodex와 대화하기" 버튼으로 떠 있어요. 기존 사이트의 색상 토큰(mint/navy)을 그대로 써서 이질감 없이 붙였어요.

3. 이중 제한으로 무료 티어 지키기

전시용 데모가 무료 API 한도를 다 써버리면 안 되니까, 두 겹으로 막았어요.

  1. 방문자(세션)당 8개 — 브라우저 쿠키로 카운트, 6시간 뒤 리셋
  2. 서버 전체 하루 300회 — 인메모리 카운터로 전체 방문자 합계를 셈

둘 중 하나라도 넘으면 실제 Gemini 호출 없이 "GitHub에서 전체 코드를 확인해보세요"로 안내가 나가요. 서버 하루 카운터는 인메모리라 서버리스 인스턴스가 재시작되면 리셋될 수 있다는 한계가 있는데, 지금 트래픽 규모에선 충분한 방어선이라 우선 이렇게 두고, 나중에 트래픽이 늘면 Vercel KV 같은 외부 저장소로 바꿀 계획이에요.

4. 보너스: 인스타 링크도 깔끔하게

작업을 마치고 인스타 프로필에 걸린 링크로 직접 들어가봤는데, 주소가 이렇게 길어져 있었어요.

https://kodex-portfolio-site.vercel.app/?utm_source=ig&utm_medium=social&...&fbclid=...

사이트 코드 문제인 줄 알았는데, 알고 보니 인스타그램이 링크를 클릭할 때 자동으로 붙이는 추적 파라미터(utm_*, fbclid)였어요. 이건 인스타 쪽에서 붙이는 거라 없앨 수는 없지만, 방문자가 사이트에 도착한 뒤 주소창만큼은 깔끔하게 보이게 만들 수는 있어서 작은 컴포넌트를 하나 추가했어요.

// src/components/UrlCleaner.tsx
useEffect(() => {
  const url = new URL(window.location.href);
  let changed = false;
  for (const key of TRACKING_PARAMS) {
    if (url.searchParams.has(key)) {
      url.searchParams.delete(key);
      changed = true;
    }
  }
  if (changed) {
    window.history.replaceState(null, "", url.pathname + url.search + url.hash);
  }
}, []);

layout.tsx에 붙여서 모든 페이지에서 동작하게 했어요. 인스타 프로필 링크 자체는 그대로 두고, git push로 재배포만 하면 그 다음부터 링크를 타고 들어온 방문자 눈엔 깨끗한 주소만 보여요.

오늘까지 진행 상황

로드맵 Phase 4가 완료됐어요. 디스코드 봇, 포트폴리오 사이트 챗 위젯 둘 다 Phase 2에서 만든 에이전트 하나를 재사용하는 구조라, 로직은 한 곳에만 있고 인터페이스만 세 개(CLI, VS Code 확장, 디스코드, 포트폴리오 사이트로 정확히는 네 개)가 됐어요.

다음 계획

로드맵 Phase 5, 정리 단계예요. 지금까지의 과정을 케이스 스터디로 정리해서 포트폴리오 사이트 devlog 섹션에 회고 글을 올릴 예정이에요.

profile
AI 서비스 기획•개발자 취업 준비생 입니다

0개의 댓글