AI SaaS를 엣지에서 거의 $0 비용으로 구축한 방법
Source: Dev.to
- 서론
몇 달 전부터 우리는 브라질 프리랜서와 소규모 사업자를 위한 AI 기반 비즈니스 제안 생성 도구인 Propoza를 만들기 시작했습니다.
문제는 실용적이었습니다: 프리랜서는 Canva나 Word에서 제안을 몇 시간씩 작성하고, 프로젝트 범위를 보호하지 못하는 일반적인 문서를 전달합니다. 도구는 간단해야 합니다 — 사용자가 서비스를 설명하면 AI가 범위, 일정, 결제 조건을 포함한 완전한 제안을 구조화합니다.
기술적 과제: 프리미엄 SaaS를 Brazilian freelancers용으로 운영하면서 revenue가 생기기 전에는 예산을 초과하지 않도록 어떻게 할까?
라이트 SaaS 또는 마이크로 SaaS는 첫 paying 고객이 생기기 전까지 $5~$20/월 정도(서버, 관리형 데이터베이스, CDN 비용)로 운영됩니다. 검증 단계 제품에겐 이 비용은 소모된 돈입니다.
우리는 다른 접근법을 선택했습니다: 모든 것을 엣지에서 구축하고 서버 없는 인프라를 사용해 서버 관리를 없앴습니다. 여기서는 성공한 점, 교훈을 얻은 트레이드오프, 그리고 배운 점을 정리합니다.
- 전통적인 SaaS 스택의 문제점
우선 우리 stack을 선택하기 전에, 일반적인 인프라에서 Brazilian SaaS를 운영할 때 최소 비용을 계산했습니다:
| Component | Typical Provider | Estimated Monthly Cost |
|---|---|---|
| Server | DigitalOcean / AWS EC2 | $8–$30 |
| Database | Managed PostgreSQL (RDS, Supabase) | $10–$40 |
| CDN | Cloudflare (paid plan) or similar | $5–$20 |
| Domain | Namecheap / Porkbun | ~$1/month |
Total: $10–$90/월
이 정도는 확립된 SaaS에겐 부담스럽지 않지만, 시장 적합성을 검증 중인 제품에겐 $100~$500를 태우기 전에 모델이 동작하는지 알 수 없다는 의미입니다.
브라질 특유의 문제: latency. São Paulo와 Rio de Janeiro에 집중된 서버는 북부 및 동북部 사용자, 특히 모바일 연결 시悪い 경험을 줍니다. CDN은 도움을 주지만 비용이 추가됩니다.
우리는 다음과 같은 조건을 충족하는 솔루션을 필요로 했습니다:
- 초기 몇 개월 동안 $0에 가깝게 비용 유지
- 전체 브라질에서 낮은 latency 제공
- 수동 개입 없이 Scaled될 수 있음
그때 우리는 엣지 서버 없는 모델을 검토했습니다.
- 선택한 스택과 이유
3.1 Cloudflare Workers 엣지 런타임 사용
애플리케이션의 핵심은 Cloudflare Workers — 전 세계 330개 이상의 데이터 센터에서 코드를 실행하는 서버 없는 런타임으로, 브라질(São Paulo, Rio de Janeiro, Fortaleza) 포인트 오브 프레즌스도 포함됩니다.
- 사용자 가장 가까운 데이터 센터에서 코드가 실행되어 Brazilian 사용자는 50ms 미만의 latency를 유지합니다.
- Workers는 Lambda와 달리 워밍된 런타임을 유지해 첫 요청과 이후 요청의 속도가 동일합니다.
- 제품이 급증하여 10,000명이 동시에 접근하더라도 Workers가 자동으로 분산시킵니다.
트레이드오프: Workers는 Node.js가 아니며, 파일 시스템 접근, 네이티브 WebSocket, Node 표준 라이브러리가 없습니다. V8 격리 런타임이기 때문에 fetch, Web Crypto, 스트림과 같은 네이티브 API만 사용 가능합니다. fs나 net을 의존하는 라이브러리는 작동하지 않습니다.
3.2 Hono HTTP 프레임워크
Worker 내부에서 ноль 오버헤드로 실행될 HTTP 프레임워크를 필요로 했습니다.
Express, Fastify, Koa와 같은 인기 있는 Node.js 프레임워크는 전체 Node.js 환경 설계되어 호환성 문제를 일으킵니다. http 모듈에 의존하고, 동기식 API를 사용하거나 서버리스 모델에 부적합한 미들웨어가 많습니다.
Hono는 이러한 제한을 피합니다. 14KB 미만이며 Workers, Deno, Bun, Node.js 모두에서 네이티브로 실행됩니다. TypeScript-first 로 설계되어 타입 추론이 강력하고, 미들웨어, 라우트 파라미터, Zod 검증을 지원합니다.
import { Hono } from 'hono'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'
const app = new Hono()
const proposalSchema = z.object({
clientName: z.string().min(1),
projectDescription: z.string().min(10),
deliverables: z.array(z.string()).min(1),
deadline: z.string(),
paymentMethod: z.string()
})
app.post('/api/proposals/generate', zValidator('json', proposalSchema), async (c) => {
const data = c.req.valid('json')
const result = await generateProposal(data)
return c.json({ proposal: result })
})
export default app
검증은 Zod를 사용해 요청 엣지에서 이루어지며, Hono의 추론 타입으로 인해 런타임 버그를 방지하면서도 처리 오버헤드를 추가하지 않습니다.
3.3 엣지에서 데이터베이스
데이터베이스 선택은 가장 어려웠습니다. 제안, 사용자, 설정을 저장해야 하는 애플리케이션에 관계형 모델이 여전히 가장 자연스럽습니다.
엣지 생태계에서 검토한 옵션 두 가지:
- D1 (Cloudflare): 분산된 관리 SQLite. Worker의 스토리지와 직접 연결되어 연결 풀 필요 없음.
- Turso: 분산된 SQLite로 지역별 복제 지원.
D1를 선택했으며, Workers와의 네이티브 통합 덕분에 로컬에 스키마를 정의하고 wrangler d1 migrations apply로 마이그레이션을 적용할 수 있습니다. 쿼리는 Worker와 동일한 데이터 센터에서 실행됩니다.
CREATE TABLE proposals (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
client_name TEXT NOT NULL,
content TEXT NOT NULL,
status TEXT DEFAULT 'draft',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
proposals_count INTEGER DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
문제점:
- D1는 모든 SQLite 쿼리를 지원하지 않음.
ALTER TABLE에 복잡한 제약 조건,RETURNING, 일부 윈도우 함수는 불가능. 배포 전wrangler dev로 테스트해야 합니다. - 쓰기 지연이 읽기보다 높음. 무료 플랜은 eventual consistency를 우선시하는데, 비즈니스 제안에겐 충분합니다.
- 마이그레이션은 작동하지만, 데이터가 많은 테이블을 altering할 때는 사전 계획이 필요합니다.
- Heavy write 접근 시 큐 또는 KV 기반 캐싱으로 분배가 필요할 수 있습니다.
3.4 Cloudflare AI Gateway
AI SaaS에서 가장 비싼 부분은 인프라가 아니라 LLM API입니다. 호출당 fractions of a penny이지만, 하루 수백 번 호출하면 빠르게 누적됩니다.
AI Gateway는 Worker와 LLM API 사이를 프록시로 삼아 다음과 같은 기능을 제공합니다:
- 응답 캐싱: 유사한 컨텍스트를 가진 두 사용자가 제안을 생성하면 캐시에서 응답을 반환.
- 사용자 별_rate limiting: 무료 플랜은 월 5개 제안까지 제한. 추가 코드 없이 게이트웨이가 적용.
- 관측성: 지연, 토큰 사용량, 오류율이 자동으로 로깅.
요청 흐름:
Request -> Worker -> AI Gateway -> Cache hit? Return cached response
-> Cache miss? LLM API -> Cache the response -> Return
초기 몇 주 동안 캐싱이 **약 40%**의 실제 LLM 호출을 절감했습니다. 많은 사용자는 비슷한 입력을 테스트합니다.
3.5 프론트엔드: React + Vite + Cloudflare Pages
React + Vite 기반 프론트엔드를 Cloudflare Pages에 호스팅합니다. 무료 티어는 월 500회 빌드와 정적 사이트에 대한 무제한 대역폭을 지원합니다.
API와의 통신은Typed fetch를 사용해 Worker와 프론트엔드가 동일한 TypeScript 타입을 공유합니다:
// 공유 타입
interface GenerateRequest {
clientName: string
projectDescription: string
deliverables: string[]
deadline: string
paymentMethod: string
}
// 클라이언트 호출
const response = await fetch('/api/proposals/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request)
})
한 가지 차이점이 된 detail: PDF는 클라이언트에서 생성되며, @react-pdf/renderer나 html2canvas + jspdf와 같은 라이브러리를 사용합니다. Work