Claude Code × GCP Cloud Functions 완전 가이드 | 서버리스 함수 초고속 개발
Claude Code로 GCP Cloud Functions를 효율화. HTTP/Pub/Sub/Firestore 트리거 구현부터 로컬 테스트·배포 자동화까지, Masa의 실무 경험을 토대로 실제 코드로 해설.
Cloud Run은 너무 과했다 — 그래서 Cloud Functions를 선택했다
저는 claudecode-lab.com을 운영하는 Masa입니다.
GCP 서버리스를 사용하기 시작했을 때 Cloud Run을 고려했습니다. 유연하고 컨테이너 기반이지만 “단순히 웹훅 하나 받는 것” 이나 “밤에 한 번 배치 실행” 같은 작업에는 분명히 오버스펙이었습니다. 그래서 Cloud Functions Gen2 로 전환했습니다.
Claude Code 덕분에 Cloud Functions 관련 코드의 90% 이상이 자동 생성됩니다.
Step 1: HTTP 트리거 함수 구현
import { http, HttpFunction } from "@google-cloud/functions-framework";
import { Request, Response } from "express";
import { Firestore } from "@google-cloud/firestore";
const db = new Firestore();
const VALID_TOKEN = process.env.API_SECRET_TOKEN;
interface ActionRequest {
userId: string;
action: string;
}
const handleAction: HttpFunction = async (req: Request, res: Response) => {
// CORS 헤더 설정
res.set("Access-Control-Allow-Origin", "*");
if (req.method === "OPTIONS") {
res.set("Access-Control-Allow-Methods", "POST");
res.set("Access-Control-Allow-Headers", "Authorization, Content-Type");
res.status(204).send("");
return;
}
// POST만 허용
if (req.method !== "POST") {
res.status(405).json({ success: false, message: "Method Not Allowed" });
return;
}
// Bearer 토큰 검증
const authHeader = req.headers.authorization ?? "";
if (!authHeader.startsWith("Bearer ") || authHeader.slice(7) !== VALID_TOKEN) {
res.status(401).json({ success: false, message: "인증되지 않음" });
return;
}
const body = req.body as Partial<ActionRequest>;
if (!body.userId || !body.action) {
res.status(400).json({ success: false, message: "userId와 action이 필요합니다" });
return;
}
try {
const logRef = await db.collection("action_logs").add({
userId: body.userId,
action: body.action,
timestamp: new Date(),
ip: req.ip,
});
res.status(200).json({ success: true, message: "액션 기록됨", logId: logRef.id });
} catch (err) {
console.error("Firestore 쓰기 오류:", err);
res.status(500).json({ success: false, message: "내부 서버 오류" });
}
};
http("handleAction", handleAction);
Step 2: Pub/Sub 트리거 함수
import { cloudEvent, CloudEvent } from "@google-cloud/functions-framework";
import { MessagePublishedData } from "@google/events/cloud/pubsub/v1/MessagePublishedData";
import { Storage } from "@google-cloud/storage";
const storage = new Storage();
interface ImageUploadedMessage {
bucketName: string;
filePath: string;
}
cloudEvent<MessagePublishedData>("handleImageUploaded", async (event: CloudEvent<MessagePublishedData>) => {
const base64Data = event.data?.message?.data;
if (!base64Data) {
console.warn("메시지 데이터 없음, 건너뜀");
return;
}
const rawJson = Buffer.from(base64Data, "base64").toString("utf-8");
let payload: ImageUploadedMessage;
try {
payload = JSON.parse(rawJson) as ImageUploadedMessage;
} catch {
console.error("Pub/Sub 메시지의 잘못된 JSON:", rawJson);
return;
}
const { bucketName, filePath } = payload;
try {
const [metadata] = await storage.bucket(bucketName).file(filePath).getMetadata();
console.log("파일 메타데이터:", { 이름: metadata.name, 크기: metadata.size });
} catch (err) {
// 예외를 던지면 Pub/Sub이 메시지를 재시도
console.error(`${filePath} 처리 실패:`, err);
throw err;
}
});
Step 3: 로컬 테스트 및 배포
# 로컬 시작
npm run build
npx @google-cloud/functions-framework --target=handleAction --port=8080
# 테스트 요청 전송
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer test-token" \
-d '{"userId": "user-123", "action": "login"}'
# GCP에 배포
gcloud functions deploy handleAction \
--gen2 \
--runtime=nodejs22 \
--region=asia-northeast3 \
--source=. \
--entry-point=handleAction \
--trigger-http \
--allow-unauthenticated \
--memory=512Mi \
--timeout=60s \
--set-secrets="API_SECRET_TOKEN=api-secret-token:latest"
4가지 함정
| 함정 | 문제 | 해결책 |
|---|---|---|
| 콜드 스타트 | 비활성 인스턴스에서 2~5초 지연 | 중요 함수에 --min-instances=1 설정 |
| 타임아웃 제한 | 최대 9분 (540초) | Pub/Sub으로 대형 작업 분할 처리 |
| Secret Manager 권한 | 런타임에서 Permission denied | secretmanager.secretAccessor 역할 부여 |
| 메모리 부족 | 무거운 처리에서 OOM | --memory=2Gi --cpu=2 설정 |
요약
| 트리거 | 사용 사례 | 핵심 고려사항 |
|---|---|---|
| HTTP | 웹훅, API 엔드포인트 | 인증, CORS |
| Pub/Sub | 비동기 이벤트 처리 | base64 디코딩, 재시도 설계 |
| Firestore | 데이터 변경에 반응 | 무한 루프 주의 |
| Cloud Scheduler | 정기 배치 작업 | OIDC 검증, 타임존 관리 |
관련 기사
무료 PDF: 5분 완성 Claude Code 치트시트
이메일 주소만 등록하시면 A4 한 장짜리 치트시트 PDF를 즉시 보내드립니다.
개인정보는 엄격하게 관리하며 스팸은 보내지 않습니다.
Claude Code 워크플로우를 한 단계 업그레이드하세요
지금 바로 Claude Code에 복사해 쓸 수 있는 검증된 프롬프트 템플릿 50선.
이 글을 작성한 사람
Masa
Claude Code를 적극 활용하는 엔지니어. 10개 언어, 2,000페이지 이상의 테크 미디어 claudecode-lab.com을 운영 중.
관련 글
Codex Automations란? 잠자는 동안 AI가 콘텐츠 운영을 처리하게 하는 방법
Codex Automations로 트래픽 분석, 주제 선정, 글 작성, CTA 개선, 배포까지 자동화하는 실전 가이드.
Claude Code로 Firestore 설계를 실패하지 않는 방법: 컬렉션보다 쿼리부터
Claude Code로 Firestore 스키마를 쿼리, 인덱스, 비용, 보안 규칙 관점에서 설계하는 실전 워크플로우입니다.
Claude Code × GCP Cloud Run 완전 가이드 | 서버리스 컨테이너 자동 배포
Claude Code로 GCP Cloud Run 배포를 빠르게. Dockerfile 생성, 자동 스케일링, CI/CD 파이프라인, Secret Manager 연동까지 실제 코드로 완전 해설.