🤖 AI 처리 대기전성분 태국기준 대조 4라벨 11항목 생성 2금지성분 체크 8▶ 일괄 실행
고객이 물어보면 이 화면을 그대로 보여줌 = 신뢰
⑤ 설정 /admin/settings
설정
견적 규칙 카테고리별 단가·기간·서류 목록 수정 코드 배포 없이 바꿈
훅 문구 h1~h5 랜딩 카피 수정 A/B 테스트용
알림 텔레그램 chat_id · 알림 조건
환율 THB→KRW (견적 계산용)
🗄️ DB 스키마 — 테이블 5개
-- ① 리드: 견적기에 들어온 모든 흔적 (중도이탈 포함)CREATE TABLE leads (
id TEXT PRIMARY KEY, -- uuid
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
hook TEXT, -- 'h1'~'h5' A/B 추적
source TEXT, -- search|customs|agency|assoc|direct
referrer TEXT,
category TEXT, -- cosmetic|food|supplement|device|goods|unknown
sku_bucket TEXT, -- '1-5'|'6-10'|'11-30'|'30+'
voucher TEXT, -- selected|planned|unknownstep INTEGER DEFAULT 1, -- 1|2|3|4(완료) ← 이탈 분석의 핵심
company TEXT,
phone TEXT,
email TEXT,
memo TEXT,
status TEXT DEFAULT 'new' -- new|contacted|quoted|won|lost
);
CREATE INDEX idx_leads_status ON leads(status, updated_at);
CREATE INDEX idx_leads_voucher ON leads(voucher, step);
-- ② 견적: 계산 결과 스냅샷 (규칙이 바뀌어도 과거 견적은 그대로)CREATE TABLE quotes (
id TEXT PRIMARY KEY,
lead_id TEXT NOT NULL REFERENCES leads(id),
created_at INTEGER NOT NULL,
category TEXT, sku_count INTEGER,
total_krw INTEGER, -- 총 비용
voucher_krw INTEGER, -- 정부 70% 부담분
self_krw INTEGER, -- 고객 실부담
days_min INTEGER, days_max INTEGER,
rules_json TEXT -- 계산 당시 규칙 원본 (재현용)
);
-- ③ 제휴처CREATE TABLE partners (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT, -- customs|forwarder|agency|assoc|media
field TEXT, -- 수행기관 분야 (겹침 판정용)
contact TEXT, phone TEXT, email TEXT,
stage TEXT DEFAULT 'listed', -- listed|contacted|talking|partnered|dead
intro_count INTEGER DEFAULT 0, -- 이 곳이 소개해준 건수 = 성과
last_touch_at INTEGER, memo TEXT
);
-- ④ 계약 고객CREATE TABLE clients (
id TEXT PRIMARY KEY,
lead_id TEXT REFERENCES leads(id),
company TEXT NOT NULL, biz_no TEXT,
contract_at INTEGER,
amount_krw INTEGER,
channel TEXT, -- direct|voucher ← 수임한도 집계에 필수
thai_holder TEXT, -- 태국 등록 명의 보유처
partner_id TEXT REFERENCES partners(id) -- 소개처
);
-- ⑤ 인허가 진행 (SKU 단위)CREATE TABLE registrations (
id TEXT PRIMARY KEY,
client_id TEXT NOT NULL REFERENCES clients(id),
product_name TEXT NOT NULL, sku_code TEXT,
doc_ingredients INTEGER DEFAULT 0, -- 전성분표
doc_cfs INTEGER DEFAULT 0, -- 판매증명서
doc_translation INTEGER DEFAULT 0,
doc_label INTEGER DEFAULT 0, -- 태국어 11항목
doc_submitted INTEGER DEFAULT 0,
status TEXT DEFAULT 'preparing',-- preparing|submitted|review|approved|rejected
submitted_at INTEGER, approved_at INTEGER,
reject_reason TEXT
);
설계 포인트 3개
· leads.step — 중도이탈을 저장해야 어느 화면이 문제인지 압니다
· quotes.rules_json — 규칙이 바뀌어도 과거 견적을 재현합니다
· clients.channel — direct/voucher를 나눠야 수임한도 집계가 됩니다
🔌 라우트 — 13개 (그중 /api/* 8개)
메서드
경로
용도
인증
GET
/
랜딩 (훅 ?h= 반영)
—
GET
/guide
태국 인허가 완전 가이드 (SEO)
—
GET
/quote
견적 3스텝 화면
—
POST
/api/lead
리드 생성/갱신 — 단계마다 호출 (upsert)
—
POST
/api/quote
견적 계산 → quotes 저장 → id 반환
—
GET
/quote/:id
견적 결과 화면
—
GET
/quote/:id/print
인쇄용 A4
—
POST
/api/consult
상담 신청 → 텔레그램 알림
—
GET
/api/admin/dashboard
집계 (오늘/이번달/훅별/유입별)
Basic
GET/PATCH
/api/admin/leads
목록·필터·상태 변경
Basic
GET/POST/PATCH
/api/admin/partners
제휴 파이프라인
Basic
GET/PATCH
/api/admin/registrations
인허가 진행 보드
Basic
POST
/api/admin/ai
성분 대조 · 라벨 생성 · 금지성분 체크
Basic
공개 API 5개는 인증 없음. 대신 레이트 리밋(IP당 분당 20회)만 겁니다.
⚙️ 견적 엔진 — 실제 조사값으로 만든 규칙표
이 표가 곧 코드입니다. ✓ 는 이 세션에서 확인한 값, ⚠ 는 설계값.
카테고리
인허가
정부수수료
기간
명의
화장품
Thai FDA 신고 ✓
1,000밧/제품 ✓
3영업일✓
태국 사업자 필수 이전 절차 없음✓
식품
수입면허 + 품목등록 ✓
분류별 상이
면허 5영업일✓
태국 사업자 필수
건강기능식품
식품 체계 준용
분류별
—
태국 사업자 필수
의료기기
Establishment License(Orr.7) + CSDT + ISO 13485 ✓
—
수개월✓
태국 법인만 외국 제조사 직접수입 불가 ✓
일반 공산품
불필요 (TISI 비대상) ✓
관세 + VAT 7%✓
통관일
—
└ TISI 대상
TISI 인증 ✓
10,000밧/건 ✓
45~90일✓
—
계산식
// 1밧 ≈ 42원 (설정에서 수정 가능)const RULES = {
cosmetic: {
govFeeTHB: 1000, // 제품당 ✓
agencyTHB: 6000, // SKU당 민간 대행 시세 ✓
holderTHB: 18000, // 명의 보유 연회비 ✓
daysMin: 3, daysMax: 3, // 서류 완비 후 영업일 ✓
prepWeeks: 6, // 서류 준비 포함 ⚠
docs: ['전성분표','CFS','LOA','제조증명','라벨'],
warn: '태국은 등록 명의 이전 절차가 없습니다'
},
device: { daysMin: 60, daysMax: 180, needs: ['ISO13485','CSDT(영문)'], hard: true },
goods: { govFeeTHB: 0, note: 'TISI 대상 아니면 인증 불필요 · 관세+VAT 7%' },
// food, supplement …
}
functionquote(category, skuCount) {
const r = RULES[category]
const cost = (r.govFeeTHB + r.agencyTHB) * skuCount + r.holderTHB
const service = SERVICE_FEE[category](skuCount) // ⚠ 내 수수료 (설계값)const total = (cost * THB_KRW) + service
return {
total,
voucher: Math.round(total * 0.7), // 중소기업 정부보조 70% ✓
self: Math.round(total * 0.3),
daysMin: r.daysMin, daysMax: r.daysMax,
docs: r.docs, warn: r.warn
}
}
⚠️ 견적 화면에 반드시 넣을 문구
"본 견적은 개요이며, 제품의 실제 분류와 서류 상태에 따라 달라집니다. 확정 견적은 상담 후 제공합니다." → 분류 오판정으로 인한 분쟁을 막습니다. 특히 의료기기/화장품 경계가 위험합니다.
🚀 배포 구조 · 개발 순서
왜 이 스택인가 — 2026-08-29 결정
🔴 Pages가 아니라 Workers입니다.
Cloudflare 공식 입장이 바뀌었습니다 — "Pages로 시작하지 마세요."
Workers가 정적 자산 + SSR을 모두 지원하고, 앞으로의 모든 투자는 Workers에 갑니다.
(Pages는 유지만) → 초안의 Pages 설계를 Workers로 정정했습니다.
후보
강점
왜 지금은 아닌가
✅ 정적 HTML + Hono
빌드 0 · SEO 최상 · 이미 쓰는 스택(fanjai 62라우트) · 되돌리기 비용 0
— 채택
React SPA + Hono
ADMIN 화면에 최적
SPA는 SEO가 약함. 채널 1번이 검색인데 치명적 → 혼합 구조가 됨
React Router v7 (SSR)
loaders/actions가 폼에 강함 · 타입 안전 라우트
가장 무거움 · SSR이 필요한 화면이 하나도 없음(가이드는 원래 정적) · v8 마이그레이션 예고
Astro
마크다운 글 = 자동 라우팅. SEO 콘텐츠에 최강
API·ADMIN은 결국 별도. 글 10개는 빌드 스크립트 20줄로 충분
판단 근거는 점수가 아니라 비대칭입니다.
잘 고르면 코드가 조금 깔끔해지고, 잘못 고르면 3주차 영업 시작이 밀립니다.
이 사업이 실패한다면 견적기를 못 만들어서가 아니라 고객이 안 와서입니다.
🔁 갈아타는 시점을 미리 정해둡니다 — 리드 100건을 넘고 ADMIN에서 하루 30분 이상
쓰게 되면, 그때 /admin만 React로 뗍니다. Hono API·D1·정적 프론트는 하나도 안 버립니다.