
어제 디스코드 봇으로 에이전트를 슬래시 커맨드까지 연결했으니, 오늘은 로드맵 Phase 4의 마지막 조각인 "무료 티어 방어"를 끝냈어요. 디스코드 봇에 사용량 캡을 걸고, 포트폴리오 사이트에도 같은 에이전트를 호출하는 챗 위젯을 넣었어요.
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커맨드도 추가했어요.
로드맵에서부터 강조했던 부분이에요 — 포트폴리오 사이트가 "저와 대화해보세요" 데모를 가지려면, 새 로직을 짜는 대신 이미 만든 에이전트를 그대로 재사용해야 한다는 원칙. kodex-code-review-agent/ask.py의 RAG 로직(질문 임베딩 → 벨로그 글 검색 → 근거 기반 답변)을 TypeScript로 그대로 옮겨서 Next.js API 라우트(/api/kodex-chat)로 만들었어요. 시스템 프롬프트, 모델, 유사도 기준까지 파이썬 버전과 동일해요.
화면에는 오른쪽 아래 "Kodex와 대화하기" 버튼으로 떠 있어요. 기존 사이트의 색상 토큰(mint/navy)을 그대로 써서 이질감 없이 붙였어요.
전시용 데모가 무료 API 한도를 다 써버리면 안 되니까, 두 겹으로 막았어요.
둘 중 하나라도 넘으면 실제 Gemini 호출 없이 "GitHub에서 전체 코드를 확인해보세요"로 안내가 나가요. 서버 하루 카운터는 인메모리라 서버리스 인스턴스가 재시작되면 리셋될 수 있다는 한계가 있는데, 지금 트래픽 규모에선 충분한 방어선이라 우선 이렇게 두고, 나중에 트래픽이 늘면 Vercel KV 같은 외부 저장소로 바꿀 계획이에요.
작업을 마치고 인스타 프로필에 걸린 링크로 직접 들어가봤는데, 주소가 이렇게 길어져 있었어요.
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 섹션에 회고 글을 올릴 예정이에요.