본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 06. 05. 12:38

개인 개발에서 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: {} }]로 정밀도가 극적으로 향상됨

  1. Gemini에 Google 검색 그라운딩 (Google Search Grounding)을 부여하면, 실시간으로 「carsensor」, 「goobike」를 참조합니다. 이것이 없으면 「2023년 시점의 지식」으로 답변하기 때문에 시세 추정이 오래된 정보가 됩니다. 무료이므로 반드시 활성화하세요.

temperature: 0.2로 안정

  1. 가격과 같은 사실적 답변은 낮은 온도 (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가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0