Pages Functions
웹 제작 건입니다. 김치프리미엄 차익거래 프로그램을 파는 분이 프로그램 소개 페이지와 문의 접수창을 원했습니다. 서버도 DB도 없이 Cloudflare Pages 위에 올려서 월 운영비가 0원이고, 문의는 텔레그램으로 바로 갑니다. 2026년 8월 5일에 정식으로 열었습니다. 작은 건인데 배포하다가 네 번 걸려 넘어졌습니다.
의뢰인은 이미 AWS Lightsail 인스턴스를 갖고 있었지만 거기에 올리지 않았습니다. 그 인스턴스는 거래소 API 키를 가진 실거래 시스템이라, 누구나 접속하는 웹페이지와 같은 서버에 두면 위험합니다. 게다가 페이지 하나와 접수 기능 하나 때문에 서버를 따로 두면 인증서 갱신과 OS 패치를 누군가 계속 챙겨야 합니다. 납품하고 끝나는 건에는 맞지 않습니다.
// functions/api/inquiry.js: 접수되면 텔레그램으로 보냄 (골자만)
export async function onRequestPost({ request, env }) {
const f = await request.formData();
if (f.get("website")) return ok(); // 허니팟: 성공 위장 폐기
if (Date.now() - +f.get("t") < 3000) return reject(); // 타임트랩
const text = escapeHtml(`[문의] ${f.get("name")} / ${f.get("contact")}\n${f.get("msg")}`);
const sends = env.CHAT_IDS.split(",").map(id => sendTelegram(env.BOT_TOKEN, id, text));
const r = await Promise.allSettled(sends);
return r.some(x => x.status === "fulfilled") ? ok() : fail();
}
wrangler pages deploy는 functions 폴더를 명령을 실행한 위치 기준으로 찾습니다. 상위 폴더에서 실행했더니 정적 파일만 올라갔습니다. 배포 출력에 Functions 번들을 올렸다는 줄이 없으면 함수가 빠진 것입니다.wrangler whoami로 대상 계정부터 확인합니다.
수신자의 chat_id를 받아 오려는데 계속 0건이었습니다. 텔레그램 봇은 상대가 /start를 누르기 전에는 메시지를 보낼 수 없습니다. 아이디를 알아도 소용없습니다.
그래서 의뢰인에게 아이디를 묻지 말고, 링크를 보내서 시작 버튼을 눌러 달라고 해야 합니다. 봇 소유권은 넘길 수 없으니 처음부터 최종 운영자 계정으로 만들어야 합니다.
수신이 되는지는 메시지를 직접 보내서 확인했습니다.
신청현황 영역은 중앙 정렬, 12건이 흘러가는 띠, 분산 배치, 알약 모양 카드 순으로 네 번 바뀌었습니다. "휑하다", "정신없다" 같은 의견을 그림 없이 말로만 주고받았기 때문입니다. 그 뒤로는 시안 두세 개 중에서 방향을 먼저 고르게 하고, 세부 조정은 그다음에 합니다. 수정 횟수가 정해진 계약에서는 이런 왕복이 그대로 손해입니다.
회원가입, 이용권, 자동 쪽지 같은 범위 밖 요구에는 별도라고만 답하지 않고 대략의 규모를 말씀드렸습니다. 규모를 듣고 의뢰인이 우선순위를 정리해 1단계만 진행했습니다. 반대로 링크가 제대로 열리지 않는 것 같은 하자는 무료로 고칩니다. 이 경계는 문서로 나눠 두었습니다.
소개 페이지와 문의 접수창 정도는 서버 없이 만들 수 있습니다.
무엇을 알리려는 페이지인지 상담에서 말씀해 주세요.