이 사이트의 Ask AI는 어떻게 만들어졌나
Workers AI 1차 + NVIDIA 폴백, 엣지 제약 하의 챗봇 설계기. 운영비 0원, 응답 약 0.6초
2026 ~ 운영 중
Summary요약
문제
예산 0원 제약(크레딧 소진형 API, RPM 한도, 무료 일일 한도) 아래에서 항상 살아있는 챗봇이 필요했습니다.
역할
라우팅 설계부터 남용 방지, 스트리밍, CI/CD까지 전체 설계·구현을 담당했습니다. Next.js static export와 Cloudflare Workers로 구축하고, Turnstile과 Durable Objects rate limit, GitHub Actions로 lint, build, E2E, deploy를 자동화했습니다.
성과
질문 성격별 3경로 라우팅으로 크레딧 소모를 최소화하고, Turnstile + Durable Object rate limit + 폴백 체인으로 운영비 0원 상태의 무중단 챗봇을 완성했습니다. Lighthouse 접근성 100, 성능 97 ~ 100, SEO 100.
Key Numbers
Technical Deep Dive
이 사이트의 Ask AI는 "연간 운영비 0원"이라는 제약 아래에서 항상 살아있는 챗봇을 만들기 위한 엣지 엔지니어링 연습장입니다. 온디바이스 AI와 마찬가지로, 엣지 환경도 결국 제한된 자원 안에서의 트레이드오프 설계가 핵심입니다.
제약 조건
- 예산 0원: Cloudflare Workers 무료 티어 + NVIDIA Build API 무료 크레딧만 사용
- NVIDIA 크레딧은 소진형: 기본 1,000회, 분당 40요청 제한 — 봇 크롤링에 노출되면 며칠 만에 소진
- Workers AI 무료 한도: 일일 한도(neurons) 초과 시 요청 실패
- 채용 담당자가 쓰는 도중에 죽어 있으면 오히려 감점
아키텍처
질문
└→ 소형 모델 분류 (llama-3.2-3b, 실패 시 portfolio로 fail-open)
├─ portfolio → Workers AI 70B (무료 한도 우선 사용) → 실패 시 NVIDIA
├─ pr_general → NVIDIA 49B (크레딧 사용, 더 큰 모델) → 실패 시 Workers AI
└─ off_limits → 정적 거절 응답 (개인 신상 질문, LLM 호출 없음)
경력·프로젝트 질문(portfolio)은 무료 한도가 있는 Workers AI가 답하고, 도메인을 벗어나되 PR 가치가 있는 질문(pr_general)만 크레딧을 쓰는 NVIDIA로 직행합니다. 개인 신상을 파고드는 질문은 분류 단계에서 차단되어 토큰을 한 개도 소모하지 않습니다.
응답은 SSE로 스트리밍합니다. Workers AI와 NVIDIA(OpenAI 호환)의 스트림 형식이 다르기 때문에, Worker에서 meta → delta → done 형태의 공통 envelope로 정규화해 클라이언트는 하나의 파서만 갖습니다.
남용 방지 3중 구조
- Cloudflare Turnstile — 매 메시지가 브라우저에서 발급된 단일 사용 토큰을 요구합니다. curl로 아무리 두드려도 siteverify를 통과하지 못하면 403입니다.
- Durable Object 기반 rate limit — IP당 분당 10회. 초과 시 429.
- 입력 검증 — 메시지 수·길이 제한, off_limits 차단.
실측으로 배운 것들
NVIDIA 무료 티어의 모델별 편차. 처음 폴백 모델로 고른 llama-3.3-70b-instruct는 유효한 키로 호출해도 60초가 지나도록 응답 자체가 오지 않았습니다. 같은 키·같은 엣지에서 llama-3.1-8b는 125ms, nemotron-super-49b는 562ms에 응답했습니다. 무료 티어에서는 "카탈로그에 있는 모델"과 "실제로 응답하는 모델"이 다릅니다. 격리 테스트(무인증 GET → 무인증 POST → 인증 POST → 모델별 비교)로 원인을 좁혀 모델을 교체했고, 타임아웃과 폴백으로 이중 안전장치를 걸었습니다.
rate limit은 믿지 말고 실측하라. Workers의 실험적(unsafe) ratelimit 바인딩은 호출은 성공하지만 40회를 연타해도 한 번도 거부하지 않았습니다. isolate 메모리 카운터도 요청이 여러 isolate로 분산되며 한도에 도달하지 못했습니다. 최종적으로 Durable Object(SQLite)의 슬라이딩 윈도우로 구현했고, 10회 허용 후 11번째부터 정확히 429가 반환되는 것을 확인했습니다.
전파 지연을 의심하라. 배포 직후의 검증 실패 중 두 건은 코드 문제가 아니라 엣지 전파가 끝나기 전의 구버전 응답이었습니다. "배포 직후 즉시 검증"은 거짓 음성(false negative)을 만듭니다.
스택
Next.js(static export) · Cloudflare Workers(정적 자산 + API 분리) · Workers AI · NVIDIA Build API · Durable Objects · Turnstile · GitHub Actions → wrangler 자동 배포