
개인 개발에서 AI를 '무료'로 통합하기: Cloudflare Workers + Gemini API
요약
Cloudflare Workers와 Gemini API를 결합하여 비용 부담 없이 AI 기능을 구현하는 방법을 소개합니다. API 키 보안을 위한 Worker Secret 활용법과 안정적인 JSON 응답을 위한 프롬프트 설계 및 파싱 전략을 다룹니다.
핵심 포인트
- Cloudflare Workers 무료 티어를 활용한 운영비 zero 구현
- Worker Secret을 이용한 안전한 API 키 관리
- JSON 응답의 안정성을 높이는 프롬프트 설계 및 3단계 폴백 전략
서론
개인 개발을 하면서 "AI 기능을 넣고 싶다"고 생각해도, 이런 고민이 있지 않으신가요?
- API 키를 클라이언트에 두고 싶지 않다
- 월간 서버 비용을 내고 싶지 않다
- 설정이 복잡할 것 같다
- 무료 티어(Free Tier)로 실용적으로 작동할지 불안하다
저도 첫 개인 개발 때 똑같은 벽에 부딪혔습니다. 최종적으로 Cloudflare Workers + Gemini API 조합으로 운영비 zero 상태에서 AI 기능을 구현할 수 있었기에, 그 구성과 구현의 포인트를 공유합니다.
실제로 이 구성으로 구동 중인 PWA:
🔗 가레지 매니저 (차검·면허 기한 관리 앱. AI로 자동차·바이크 매입 시세 추정)
왜 Cloudflare Workers + Gemini API 인가
| 관점 | 이 구성 | 대안 (AWS Lambda + OpenAI 등) |
|---|---|---|
| 월간 고정비 | ¥0 (무료 티어로 충분) | ~$5/월 + API 사용료 |
| 설정의 복잡성 | wrangler 명령어 하나로 완결 | IAM·VPC 등의 지식 필요 |
| 배포 속도 | 수 초 | 수십 초~수 분 |
| 글로벌 배포 | 자동 (300+ 거점) | 리전(Region) 선택 필요 |
| API 키 보관 | Worker Secret으로 완결 | Secrets Manager 등이 필요 |
특히 **"Worker Secret"**이 개인 개발에 최고이며, 터미널 명령어 하나로 안전하게 키를 둘 수 있습니다.
아키텍처
[브라우저 (PWA)]
│
│ POST /api/market-price
...
클라이언트에는 API 키가 전혀 전달되지 않으므로 안전합니다.
구현: Worker 측
worker/index.ts:
interface Env {
ASSETS: { fetch: (request: Request) => Promise<Response> }
GEMINI_API_KEY: string // ← Secret으로 보관
...
}
wrangler.jsonc:
{
"name": "myapp",
"main": "worker/index.ts",
...
}
이것만으로 **"정적 사이트 배포 + API 엔드포인트"**가 하나의 Worker로 완결됩니다.
API 키의 안전한 보관
가장 중요한 포인트. .env 파일이나 wrangler.jsonc에 직접 쓰지 않고, Worker Secret을 사용합니다.
npx wrangler secret put GEMINI_API_KEY
# → 프롬프트에서 API 키를 입력
이를 통해:
- ✅ 소스 코드에 포함되지 않음
- ✅ Git에 커밋되지 않음
- ✅ 런타임에서
env.GEMINI_API_KEY로 읽을 수 있음 - ✅ Cloudflare 대시보드에서 암호화 저장
클라이언트 JS에는 절대로 전달되지 않으므로, 브라우저를 통해 유출될 걱정이 없습니다.
프롬프트 설계의 팁
JSON을 확실하게 반환받기 위해 다음을 준수했습니다:
const prompt = `당신은 일본의 중고차·바이크 매입 시장의 시세 전문가입니다.
다음 차량에 대해, Google 검색을 사용하여 현재 실매매 가격을 조사하고,
매입 시세의 기준을 추정해 주세요.
...
포인트:
- 역할을 명시 ("전문가입니다")
- 형식을 엄격화 ("JSON으로만", "서론 불필요")
- null 허용을 명기 (모델이 추측으로 채우는 것을 방지)
- 코드 펜스(Code Fence) 금지를 명시 (모델은 멋대로 펜스를 붙이곤 함)
응답 파싱 전략
그럼에도 모델은 가끔 펜스를 붙이거나 서론을 작성하므로, **3단계 폴백(Fallback)**으로 파싱합니다:
// 1. 코드 펜스 제거
const fenceCleaned = text
.replace(/^\s*```(?:json)?\s*/i, '')
.replace(/\s*```\s*$/i, '')
.trim()
// 2. 그대로 JSON 파싱 시도
let parsed: unknown
...
이로써 실운영에서 99% 파싱에 성공합니다.
빠졌던 포인트 (배움)
tools: [{ google_search: {} }]로 정밀도가 극적으로 향상됨
- Gemini에 Google 검색 그라운딩 (Google Search Grounding)을 부여하면, 실시간으로 「carsensor」, 「goobike」를 참조합니다. 이것이 없으면 「2023년 시점의 지식」으로 답변하기 때문에 시세 추정이 오래된 정보가 됩니다. 무료이므로 반드시 활성화하세요.
temperature: 0.2로 안정
- 가격과 같은 사실적 답변은 낮은 온도 (Low Temperature)가 좋습니다. 1.0이면 답변이 흔들립니다.
3. 개인 식별 정보는 보내지 말 것
프롬프트에 「성명·주소·번호판」을 포함하지 않도록, 프론트엔드 측에서 전송 데이터를 제한했습니다:
// ❌ 보내지 않는 필드
// name, plateNumber, vin, address
// ✅ 보내는 필드 (추정에 필요)
...
개인정보 처리방침에도 이 분리를 명시했습니다.
4. 캐시는 localStorage로
매번 API를 호출하면 무료 할당량 (Free Tier)을 소비하므로, 차량 ID 단위로 7일간 캐싱합니다:
const cached = localStorage.getItem(`marketPrice:${vehicleId}`)
if (cached) {
const data = JSON.parse(cached)
...
이것만으로 API 호출이 1/10 이하로 줄었습니다.
요약
| 구성 요소 | 역할 | 월간 비용 |
|---|---|---|
| Cloudflare Workers (정적 배포 + API) | 프론트엔드 + 서버리스 함수 | ¥0 (일일 10만 req까지 무료) |
| ... | 합계 | ¥0/월 |
이로써 개인 개발의 AI 기능을 「월 고정비 제로 · 서버리스 · API 키 유출 없음」으로 구현할 수 있습니다.
기술력이 높지 않은 초보자인 저도 구축할 수 있었던 구성이므로, 관심이 있다면 따라 해 보세요.
실제로 작동 중인 앱 예시:
🔗 가레지 매니저 (Garage Manager)
질문이나 지적은 X로 편하게 보내주세요📩
🔗 @slipon_xxx (← 실제 핸들로 교체)
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기