5단계 확인 및 제출 페이지 — 제출 후 실제 진행 기능 정리
목적: www 온보딩 위저드 5단계(확인 및 제출) — 즉 사용자 정보 확인 페이지 — 에서 사용자가 확인한 정보와 「시작하기」 클릭 후 현재 코드 기준으로 실제로 진행되는 기능을 분석해 문서화한다. §1.3에는 해당 화면의 표시 항목·예시 값·버튼 구성을 정리하였다. 코드 생성 없음 — 분석·기획 문서만 포함.
참조: tenant-onboarding-demo-www-plan.md, tenant-onboard-resource-allocation-flow-plan.md, tenant-onboarding-flow.md, control-plane-zuplo-vs-direct-worker.md (Control Plane Zuplo 경유 vs Worker 직호출 비교·추천), apps/www (app.js, api.js), prego-control-plane, .github/workflows/provision-tenant.yml.
1. 5단계 화면(확인 및 제출) 요약
5단계는 사용자 정보 확인 페이지로, 1~4단계에서 입력·선택한 내용을 요약해 보여주고, 사용자가 「시작하기」 를 눌러 최종 제출하는 단계이다.
1.1 화면에 표시되는 확인 항목
| 확인 항목 | 설명 | 데이터 소스 |
|---|---|---|
| 플랜 (Plan) | free / basic / professional / enterprise | 1단계 선택 값 wizardState.plan_tier |
| 서브도메인 (Subdomain) | {subdomain_name}.pregoi.com | 4단계 입력 wizardState.slug / subdomain_name |
| 회사명 (법인명) | Company Name (Legal Name) | 4단계 wizardState.company_name |
| 약어 (Abbreviation) | 2~5자 (선택) | 4단계 wizardState.abbr |
| 관리자 (Administrator) | 이름 <이메일> | 4단계 admin_name, admin_email |
| 관리자 전화번호 | Administrator Phone Number | 4단계 wizardState.admin_phone |
| 추가 사용자 (Additional Users) | N명 (연동 예정) | 4단계 wizardState.additional_users 길이 |
1.2 버튼 동작
- 이전: 4단계(테넌트 정보 입력)로 되돌아감.
- 시작하기: 위 확인 내용을 기준으로 제출을 실행하고, 성공 시 6단계(프로비저닝 대기)로 전환.
1.3 화면 예시(참조)
5단계 화면은 확인 및 제출 타이틀 아래 “입력 내용을 확인한 뒤 시작하기를 누르세요.” 안내 문구가 있으며, 아래 항목이 키-값 형태로 표시된다. (다크 모드 지원 시 동일 구성.)
| 화면 표시 항목 | 예시 값 | 비고 |
|---|---|---|
| 플랜 (Plan) | free | 1단계 선택 |
| 서브도메인 (Subdomain) | lee.pregoi.com | 4단계 slug/subdomain_name |
| 회사명 (법인명) | lee kim consulting pte ltd | 4단계 company_name |
| 약어 (Abbreviation) | LE | 4단계 abbr (2~5자) |
| 관리자 (Administrator) | marco baik <marco@gokiri.com> | 4단계 admin_name, admin_email |
| 관리자 전화번호 | +6581618767 | 4단계 admin_phone |
| 추가 사용자 (Additional Users) | 1명 (연동 예정) | 4단계 additional_users 배열 길이 표시 |
하단 버튼: 이전 (보조), 시작하기 (주요 액션, 강조 스타일). 「시작하기」 클릭 시 위 표에 나온 값들이 그대로 POST /v1/tenants 요청 body로 전달된다.
2. 「시작하기」 클릭 시 실제 진행 흐름 (현재 코드 기준)
플랜이 무료(free) 인 경우와 유료(basic/professional/enterprise) 인 경우가 다르다.
유료는 3단계에서 이미 「결제하기」로 Stripe Checkout에 진입했으므로, 5단계까지 오는 경로는 주로 무료 플로우이다. 아래는 무료 플랜에서 「시작하기」를 눌렀을 때의 흐름이다.
2.1 클라이언트(www) 동작
| 순서 | 담당 | 동작 | 코드 위치 |
|---|---|---|---|
| 1 | apps/www (app.js) | 「시작하기」 버튼(#btn-submit) 클릭 시 bindStep5Submit 핸들러 실행. | bindStep5Submit() |
| 2 | apps/www (api.js) | PregoAPI.createTenantFree(payload) 호출. payload: tier, region, subdomain_slug, subdomain_name, company_name, abbr, admin_email, admin_name, admin_phone, additional_users. | createTenantFree() |
| 3 | apps/www (api.js) | PREGO_CONTROL_PLANE_URL 이 설정된 경우 POST /v1/tenants 요청 전송. Body: 위 payload(JSON). | fetch(base + ‘/v1/tenants’, { method: ‘POST’, … }) |
| 4 | apps/www (app.js) | 응답에서 job_id(및 tenant_id) 수신. 6단계로 전환(goToStep(6)), pollJobStatus(job_id) 로 주기적 상태 조회 시작. | createTenantFree().then(…) |
| 5 | apps/www (api.js) | 6단계에서 GET /v1/jobs/:job_id 로 상태 조회. Completed 시 origin_url 표시, Failed 시 실패 메시지 표시. | getJobStatus(jobId) |
무료가 아니거나 PregoAPI가 없으면, 데모용 mock job_id로 6단계만 표시하고 폴링한다.
2.2 Control Plane 수신 — API·DB·Placement·트리거
| 순서 | 담당 | 동작 | 코드 위치 |
|---|---|---|---|
| 6 | prego-control-plane | POST /v1/tenants 수신. Body 검증(tier, region, subdomain_slug 등). | index.ts → tenants.ts validateCreateBody, enqueueProvisionJob |
| 7 | prego-control-plane | Placement 결정: decidePlacement(db, tenant_id, plan_tier, region) 호출. 결과: create_new_server 또는 target_server_id(기존 노드). R2: server_metrics 기반 용량·R4: plan별 role(shared/dedicated) 반영. | placement.ts |
| 8 | prego-control-plane | D1 tenants_master 에 행 삽입(tenant_id, status=Pending, region, plan_tier, subdomain_slug, subdomain_name, company_name, abbr, admin_email, admin_name, admin_phone, additional_users 등). | tenants.ts |
| 9 | prego-control-plane | D1 provision_jobs 에 행 삽입(job_id, tenant_id, trace_id, region, status=Pending, plan_tier, infra_mode, create_new_server/target_server_id 반영). | tenants.ts |
| 10 | prego-control-plane | 202 응답으로 { job_id, tenant_id } 반환. (Option B) prego-provision-queue 에 메시지 전송 또는 (Option A) workflow_dispatch 로 GitHub Actions provision-tenant.yml 호출. 전달 인자: job_id, tenant_id, region, create_new_server, target_server_id, subdomain_slug, canonical_hostname 등. | webhooks-stripe.ts / tenants.ts, provision-dispatch |
5단계에서 확인한 플랜·서브도메인·회사명·약어·관리자(이메일/이름/전화)·추가 사용자는 모두 POST /v1/tenants 의 body로 전달되며, Control Plane이 D1 tenants_master 및 이후 워크플로 입력에 반영한다.
2.3 GitHub Actions — 서버 해석·DNS·Ansible·Zuplo·콜백
| 순서 | 담당 | 동작 | 코드/설정 |
|---|---|---|---|
| 11 | provision-tenant.yml | resolve-server job: target_server_id 있으면 GET /internal/nodes/:node_id (R1)로 server_ip·node_id 조회. create_new_server 이면 Pulumi up으로 신규 서버·db_server_ip 획득. 필요 시 POST /internal/nodes (R3)로 새 노드 등록. GET /internal/db-host?region= (R7)로 db_host 조회(설정 시), 없으면 Pulumi 출력·vars 사용. | .github/workflows/provision-tenant.yml |
| 12 | provision-tenant.yml | tenant-dns job: Cloudflare에 canonical (tenant-{short_id}.pregoi.com) 및 사용자 서브도메인 CNAME 생성. | tenant-dns 단계 |
| 13 | provision-tenant.yml | ansible-provision job: GET /internal/billing?tenant_id= 호출 → company_name, abbr, plan_limits (R5) 포함한 billing_extra.json 생성. 인벤토리 동적 생성(server_ip, db_server_ip). Ansible playbook 실행 시 -e tenant_id=... -e @billing_extra.json 등으로 회사명·약어·플랜 한도 전달. Frappe 사이트 생성, Administrator API Key 발급. | Fetch billing, Create inventory, Run Ansible |
| 14 | provision-tenant.yml | Zuplo Sync: Ansible에서 발급한 API Key로 Zuplo Consumer 등록. 메타에 plan_tier (R6) 전달. | zuplo_sync —plan-tier |
| 15 | provision-tenant.yml | POST /internal/provision-complete 호출. job_id, tenant_id, status=Completed, host, site_name, origin_url 등 전달. | provision-complete 콜백 |
| 16 | prego-control-plane | 콜백 수신 시 D1 provision_jobs.status → Completed, tenants_master.status → Active, tenant_runtime 갱신, TENANT_ORIGINS KV에 hostname → origin 기록. | internal.ts handleProvisionComplete |
이후 www 6단계의 GET /v1/jobs/:job_id 폴링에서 status=Completed, origin_url 이 반환되면 사용자에게 테넌트 URL이 노출된다.
3. 5단계 확인 항목과 백엔드 사용처 매핑
| 5단계 확인 항목 | API·DB·워크플로 반영 내용 |
|---|---|
| 플랜 (Plan) | plan_tier. Control Plane D1 tenants_master·provision_jobs. Placement 시 R4(role 필터)·R2(용량). 워크플로에서 billing·plan_limits(R5)·Zuplo plan_tier(R6) 조회·전달. |
| 서브도메인 | subdomain_slug, subdomain_name. POST /v1/tenants body → D1. 워크플로에서 DNS CNAME(subdomain.pregoi.com → canonical)·Ansible·Zuplo slug/subdomain 메타. |
| 회사명 (법인명) | company_name. D1 tenants_master. 워크플로에서 GET /internal/billing → billing_extra.json → Ansible -e company_name=... (Frappe·아티팩트 등에 반영). |
| 약어 (Abbreviation) | abbr. D1 tenants_master. GET /internal/billing 응답 → billing_extra → Ansible extra vars. |
| 관리자 (이름·이메일) | admin_name, admin_email. D1 tenants_master. 프로비저닝 단계에서 Frappe Administrator·연동 정책에 따라 사용(Ansible 등). |
| 관리자 전화번호 | admin_phone. D1 tenants_master. 보관·연동 정책에 따라 사용. |
| 추가 사용자 | additional_users (배열). D1 tenants_master(JSON 등). 워크플로·Ansible에서 “연동 예정” 등으로 추가 사용자 초대·연동 절차에 활용 가능. |
4. 요약 — 5단계 「시작하기」 이후 실제 진행 기능
-
www
확인한 내용을 그대로 POST /v1/tenants 로 전송하고, job_id 수신 후 6단계에서 GET /v1/jobs/:job_id 로 상태 폴링. -
Control Plane
tenant_id·job_id 생성, Placement(R2·R4) 결정, D1 tenants_master·provision_jobs 저장, workflow_dispatch 또는 Queue 로 프로비저닝 워크플로 트리거. -
워크플로
서버 해석(R1·R3·R7) → DNS 생성 → billing·plan_limits(R5) 조회 후 Ansible 실행(회사명·약어·플랜 한도 반영) → Zuplo Sync(R6) → provision-complete 콜백. -
사용자
6단계에서 job 상태가 Completed 가 되면 origin_url 로 테넌트 접속 가능.
위 내용은 현재 코드( prego-control-plane, Prego apps/www, .github/workflows/provision-tenant.yml, prego-ansible 등) 를 기준으로 한 실제 동작 정리이며, 추후 UI/API 변경 시 이 문서를 갱신하면 된다.