20. 웹앱 자동화 가이드 - Google Apps Script vs Cloudflare Workers¶
핵심: "무료로 빠르게 만들기"는 Apps Script, "빠르고 전문적으로 운영하기"는 Cloudflare Workers. 프로토타입 → Apps Script, 실서비스 → Cloudflare가 가장 효율적인 순서.
언제 무엇을 쓰는가¶
"웹으로 자동화하고 싶다"
|
├─ 구글 시트/폼 기반이면 충분한가?
| ├─ YES → Google Apps Script
| └─ NO → Cloudflare Workers
|
├─ 외부 사용자(고객)가 접근하는가?
| ├─ YES + 속도/URL 중요 → Cloudflare Workers
| └─ YES + 속도 괜찮음 → Apps Script도 가능
|
└─ 커스텀 도메인이 필요한가?
├─ YES → Cloudflare Workers
└─ NO → Apps Script
상세 비교¶
| 항목 | Google Apps Script | Cloudflare Workers |
|---|---|---|
| 비용 | 완전 무료 | 무료 (일 10만 요청까지) |
| 로딩 속도 | 3~10초 (콜드 스타트) | 0.1~0.5초 |
| 데이터 저장 | 구글 시트 (내장) | D1 (SQLite DB) |
| 이메일 | MailApp 한 줄 | Resend API 연동 필요 |
| SMS | 외부 API (알리고 등) | 동일 |
| 캘린더 | CalendarApp 한 줄 | Google Calendar API 연동 |
| URL | script.google.com/macros/s/매우긴ID/exec | 커스텀 도메인 가능 |
| 디자인 | 제한적 (iframe 안에 렌더링) | 완전 자유 |
| 배포 | 배포 관리 > 새 버전 | wrangler deploy |
| 코드 수정 | 브라우저 편집기에서 복사/붙여넣기 | 로컬 파일 수정 > 명령어 배포 |
| 인증 | 구글 계정 또는 PIN | 자유롭게 구현 |
| 개발 난이도 | 중 (JavaScript) | 중~상 (TypeScript) |
Google Apps Script 핵심 정리¶
구조¶
구글 시트 (데이터 저장)
|
└─ Apps Script (코드 실행)
├─ doGet(e) ─────── 웹 페이지 서빙
├─ 서버 함수들 ────── 비즈니스 로직
└─ HTML 파일들 ───── 프론트엔드 (google.script.run으로 서버 호출)
핵심 패턴¶
1. 웹앱 라우팅 (URL 파라미터로 페이지 분기)
function doGet(e) {
var page = e.parameter.page || 'main';
var template = HtmlService.createTemplateFromFile('Page' + page);
return template.evaluate();
}
2. HTML에서 서버 함수 호출
// 프론트엔드 (HTML)
google.script.run
.withSuccessHandler(function(result) { /* 성공 */ })
.withFailureHandler(function(err) { /* 실패 */ })
.서버함수이름(인자1, 인자2);
3. 트리거 (자동 실행) - 폼 제출 시: onFormSubmitHandler - 시트 수정 시: onEditHandler - 시간 기반: 6시간마다 체크 (미응답 알림 등)
4. 내장 서비스
MailApp.sendEmail({to, subject, body}); // 이메일
CalendarApp.createEvent(title, start, end); // 캘린더
SpreadsheetApp.getActiveSheet(); // 시트
주의사항¶
- 시간 값 자동 변환: "14:00" 입력하면 시트가 Date 객체로 변환해버림 →
setNumberFormat('@')텍스트 강제 - 콜드 스타트: 오래 안 쓰면 첫 로딩 10초 이상
- 배포 시 버전: 코드 수정 후 반드시 "새 버전"으로 배포해야 반영
- URL 길이: 매우 길고 지저분함, 커스텀 도메인 불가
Cloudflare Workers 핵심 정리¶
구조¶
Cloudflare Edge (전 세계 300+ 데이터센터)
|
├─ Workers (서버 코드, TypeScript)
| └─ Hono (경량 웹 프레임워크)
|
├─ D1 (SQLite 데이터베이스)
|
├─ Assets (정적 파일: HTML/CSS/JS)
|
└─ 외부 연동
├─ Resend (이메일 API)
├─ 알리고 (SMS API)
└─ Google Calendar API
핵심 패턴¶
1. Hono 라우팅 (REST API)
const app = new Hono();
app.get('/api/data/:id', async (c) => {
const id = c.req.param('id');
const row = await c.env.DB.prepare('SELECT * FROM table WHERE id=?').bind(id).first();
return c.json({ success: true, data: row });
});
app.post('/api/action', async (c) => {
const body = await c.req.json();
// 처리...
return c.json({ success: true });
});
2. 프론트엔드에서 API 호출 (fetch)
const resp = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, phone, email })
});
const result = await resp.json();
3. D1 데이터베이스
// 읽기
const row = await c.env.DB.prepare('SELECT * FROM requests WHERE id=?').bind(id).first();
// 쓰기
await c.env.DB.prepare('INSERT INTO requests (name, phone) VALUES (?, ?)').bind(name, phone).run();
4. 환경 변수 & 시크릿
Apps Script → Cloudflare 이전 체크리스트¶
- [ ] google.script.run → fetch('/api/...') 변환
- [ ] MailApp → Resend API
- [ ] CalendarApp → Google Calendar API (서비스 계정)
- [ ] SpreadsheetApp → D1 (SQL)
- [ ] doGet 라우팅 → Hono 라우팅
- [ ] 시간 트리거 → Cron Triggers (wrangler.toml에 설정)
- [ ] HTML 템플릿 (= ?>) → URL 파라미터 + JS로 처리
이메일 발송 비교¶
Apps Script¶
MailApp.sendEmail({ to: 'user@email.com', subject: '제목', body: '내용' });
// 끝. 한 줄.
// 발신: 구글 계정 이메일로 자동 발송
// 한도: 무료 계정 100통/일
Cloudflare + Resend¶
await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: { Authorization: 'Bearer API키', 'Content-Type': 'application/json' },
body: JSON.stringify({
from: '우리집인테리어디자인 <noreply@medinterior.com>', // 커스텀 발신 주소!
to: ['user@email.com'],
subject: '제목',
text: '내용'
})
});
// 장점: 커스텀 도메인 발신, HTML 이메일, 발송 추적
// 무료: 100통/일, 월 3,000통
실전 교훈 (미팅 예약 시스템에서 배운 것)¶
1. 프로토타입 먼저¶
- Apps Script로 기능/플로우 검증 → 확정된 후 Cloudflare로 이전
- "작동하는 프로토타입"이 있으면 이전할 때 스펙이 명확해서 훨씬 빠름
2. 구글 시트의 함정¶
- 시트에 "14:00" 입력 → Date 객체로 자동 변환 → "Sat Dec 30 1899 14:00:00" 출력
- 해결:
setNumberFormat('@')(텍스트 강제) + 읽을 때 Date instanceof 체크
3. URL 설계가 UX¶
- Apps Script:
script.google.com/macros/s/AKfyc.../exec?page=customer&id=5&token=abc - Cloudflare:
woori-meeting.medinterior.com/customer/5/abc - 고객이 보는 URL이 깔끔해야 신뢰감
4. 콜드 스타트 체감¶
- Apps Script: 3~10초 (첫 로딩). 자주 쓰면 줄어들지만, 고객이 처음 접하는 순간은 항상 느림
- Cloudflare Workers: 0.1~0.5초. 체감 차이가 큼
5. 메시지 톤은 코드보다 중요¶
- 코드를 다 만든 후에도 메시지 톤 조정에 시간이 많이 들었음
- "맞춰드리겠습니다" → "최대한 조율해보겠습니다" (약속 vs 노력)
- "추후 안내" → 빈칸 (없는 정보는 안 보여주는 게 낫다)
- 메시지는 별도 텍스트 파일로 관리 → 비개발자가 직접 검토/수정 가능
비용 정리¶
| 서비스 | 무료 한도 | 유료 시작 |
|---|---|---|
| Apps Script | 이메일 100통/일, 트리거 20개 | 거의 안 넘음 |
| Cloudflare Workers | 10만 요청/일 | $5/월 |
| Cloudflare D1 | 500만 행 읽기/일, 10만 쓰기/일 | $0.75/100만 |
| Resend | 100통/일, 월 3,000통 | $20/월 (5만통) |
| 알리고 SMS | 없음 (선불) | 건당 8~25원 |
소규모 비즈니스는 전부 무료 티어 안에서 운영 가능.