www 회원가입 및 Google 간편가입 기능 기획서
작성일: 2025-03-04
대상: Prego/apps/www (온보딩 포털)
참조: Prego/apps/client-web (OTP 프로세스), prego-zuplo (메일 API·Auth API)
1. 개요
www 포털에서 회원가입 시 이메일 OTP 인증과 Google 간편가입을 지원한다.
- 이메일 OTP: client-web의 OTP 프로세스를 참조하여 동일한 패턴으로 구현
- 메일 발송: Zuplo의 기존 메일 전송 API를 활용
- Google 로그인: 이미 연동된 Google API ID/Key를 사용한 간편가입
2. 언어 및 지역 정책
2.1 기본 언어: 영문
- 모든 www 페이지는 기본으로 영문(English)만 사용한다.
- UI 텍스트, 버튼, 라벨, 에러 메시지 등은 영문으로 작성한다.
- 향후 다국어 지원을 고려하여 구조는 확장 가능하게 설계한다.
2.2 접속 국가 파악 및 포워딩
- 사용자 접속 시 Cloudflare를 활용하여 접속 국가를 파악한다.
- 가능한 수단:
- CF-IPCountry 헤더: Cloudflare가 프록시로 사용될 때 클라이언트 IP 기반 국가 코드(ISO 3166-1 Alpha-2)를 제공
- Cloudflare Workers 또는 Pages 환경에서
request.cf?.country또는request.headers.get('CF-IPCountry')로 조회
- 해당 국가에 맞는 웹사이트/도메인으로 포워딩할 수 있는 로직을 준비한다.
- 현재 단계: 향후 다국어·다국가 지원을 위해 인프라만 설계하고, 기본은 영문 단일 버전으로 운영한다.
2.3 상단 언어·국가 선택 UI
- 모든 페이지 **상단(헤더)**에 언어(Language) 및 국가(Country) 선택 옵션을 둔다.
- 사용자가 언제든지 언어·국가를 변경할 수 있도록 한다.
- 변경 시:
- 선택한 언어/국가를
localStorage또는 쿠키에 저장 - 해당 설정에 맞는 페이지로 이동하거나, 향후 다국어 적용 시 번역된 컨텐츠를 로드
- 선택한 언어/국가를
2.4 기본 언어 우선순위
- 1순위: 사용자가 이전에 선택한 언어(저장된 값)
- 2순위: 브라우저 언어(
navigator.language또는Accept-Language헤더) - 3순위: 영문(English) — 지원하지 않는 브라우저 언어인 경우
- 현재는 영문만 지원하므로, 1·2순위가 영어가 아니어도 기본 출력은 영문으로 하되, 향후 다국어 적용 시 이 우선순위를 사용한다.
3. 기존 인프라 정리
3.1 client-web OTP 프로세스 (참조)
| 단계 | 페이지 | API | 설명 |
|---|---|---|---|
| 1 | signup | POST /auth/otp/request | 이메일 입력 후 인증코드 발송 요청 |
| 2 | verify-email | POST /auth/otp/verify | 6자리 코드 입력 후 검증 |
관련 파일:
apps/client-web/app/signup/page.tsx: 이메일 폼,handleSubmit→POST /auth/otp/request { email, lang }apps/client-web/app/[companyId]/[lang]/auth/verify-email/page.tsx:CodeEntryForm(6자리 OTP),handleSuccess→POST /auth/otp/verify { email, code }apps/client-web/components/passcode/code-entry-form.tsx: OTP 6자리 입력 UI (OtpDigitBoxes,masked=false)apps/client-web/components/passcode/otp-digit-boxes.tsx: 6칸 입력 박스, paste 지원
client-web API 호출 패턴:
// 1. 인증코드 발송fetch(getAuthApiUrl('/auth/otp/request'), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, lang })})// 성공 시 → sessionStorage.setItem(AUTH_PENDING_EMAIL, email) → router.push(verifyEmailPath)
// 2. 인증코드 검증fetch(getAuthApiUrl('/auth/otp/verify'), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, code }), credentials: 'include'})3.2 Zuplo 메일 전송 API
- POST
/email(config/25-email.oas.json)- 요청:
{ to, subject, content, tenant_id? } - 인증: API Key (Bearer)
- Rate limit: 50/min
- 동작:
EMAIL_QUEUE_GATEWAY_URL로 forward → Queue → 실제 발송
- 요청:
3.3 Zuplo Auth API (기존)
- POST
/auth/otp/request(config/00-security.oas.json):AUTH_WORKER_URL로 forward - POST
/auth/otp/verify(config/00-security.oas.json):AUTH_WORKER_URL로 forward
→ client-web은 이 경로를 사용. AUTH_WORKER가 OTP 생성·저장·이메일 발송 담당.
3.4 Zuplo Auth API (05-auth, www용)
- POST
/auth/email/send-otp: 이메일 OTP 발송 (Control Plane D1 + Resend) - POST
/auth/email/verify-otp: OTP 검증 후 로그인 (JWT 발급) - GET
/auth/google: Google OAuth 시작 - GET
/auth/google/callback: Google OAuth 콜백 → JWT 발급
→ www 온보딩용. D1 users/sessions/otps 테이블 사용.
3.5 Google API 연동 상태
- Google Client ID, Client Secret 이미 연동됨
auth-handler.ts에서GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REDIRECT_URI사용
4. www 회원가입 페이지 설계
4.1 페이지 구조
| 페이지 | 경로 | 역할 |
|---|---|---|
| 회원가입 (이메일 입력) | signup.html | 이메일 입력 → 인증코드 발송 |
| 이메일 인증 | signup-verify.html | 6자리 OTP 입력 → 검증 후 계정 생성/로그인 |
| Google 간편가입 | (버튼) | /auth/google 리다이렉트 → 콜백 후 로그인 |
4.2 이메일 OTP 플로우
- 사용자가
signup.html에서 이메일 입력 후 “인증코드 받기” 클릭 POST /auth/email/send-otp호출 ({ email })- Zuplo auth-handler:
- 6자리 OTP 생성
- Control Plane
POST /internal/auth/create-otp로 D1 저장 - 이메일 발송: Zuplo POST
/email또는 Resend API
- 성공 시
signup-verify.html?email=...로 이동 (또는 sessionStorage에 email 저장 후 이동) signup-verify.html에서 6자리 코드 입력POST /auth/email/verify-otp호출 ({ email, code })- 성공 시 JWT 발급,
index.html또는dashboard.html로 리다이렉트
4.3 메일 발송 경로
옵션 A (권장): auth-handler에서 Resend 직접 호출 (현재 구현)
- 장점: 구현 완료, 의존성 단순
- auth-handler 내
RESEND_API_KEY사용
옵션 B: auth-handler에서 Zuplo POST /email 호출
- Zuplo API Key 필요
fetch(ZUPLO_BASE_URL + '/email', { headers: { Authorization: 'Bearer ' + ZUPLO_EMAIL_API_KEY }, body: { to, subject, content } })- 메일 발송을 Zuplo 한 곳으로 통합
→ 기획서에서는 옵션 A 기준으로 기술. 필요 시 옵션 B로 전환 가능.
4.4 OTP 이메일 템플릿
client-web 연동 시 Auth Worker가 사용하는 형식과 유사하게:
제목: Prego 로그인 인증 코드본문: 6자리 코드 [CODE], 10분 유효auth-handler.ts의 authEmailSendOtpHandler에서 이미 Resend로 발송 중.
5. Google 간편가입 설계
5.1 플로우
signup.html또는index.htmlStep 2에 “Google로 계속하기” 버튼- 클릭 시
window.location.href = PREGO_AUTH_URL + '/auth/google?return_url=' + encodeURIComponent(returnUrl) - Zuplo
/auth/google→ Google OAuth 화면으로 리다이렉트 - 사용자 동의 후
/auth/google/callback호출 - auth-handler: 토큰 교환 → 사용자 정보 조회 → D1 users upsert → JWT 발급 →
return_url로 리다이렉트 (Set-Cookie: PREGO_JWT)
5.2 연동 페이지
signup.html: “Google로 간편 가입” 버튼index.htmlStep 2 (로그인): 기존 “Google로 계속하기” 버튼 유지
5.3 환경 변수 (이미 설정된 것으로 가정)
GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URI(예:https://{zuplo-domain}/auth/google/callback)
6. www 신규·수정 파일
6.1 신규 페이지
| 파일 | 설명 |
|---|---|
signup.html | 회원가입 진입: 이메일 입력, Google 버튼 |
signup-verify.html | 6자리 OTP 입력 (client-web verify-email 패턴) |
6.2 수정 파일
| 파일 | 수정 내용 |
|---|---|
index.html | 상단 언어·국가 선택 UI 추가; “Sign up” 링크 → signup.html; 모든 UI 영문 |
api.js | sendEmailOtp, verifyEmailOtp, getGoogleAuthUrl (이미 존재 시 확인) |
styles.css | signup·verify 페이지용 스타일; 상단 locale 선택 UI 스타일 |
_headers 또는 Workers | Cloudflare CF-IPCountry 활용한 국가 파악 (배포 환경에 따라) |
6.3 signup.html 구성
- 상단 공통: 언어·국가 선택 (Language, Country) — §2.3
- 로고
- 제목: “Sign up” (영문)
- 이메일 가입
- 이메일 input
- “Send verification code” 버튼
- 구분선: “or”
- Google 간편가입
- “Continue with Google” 버튼
- “Already have an account? Log in” 링크 →
index.html또는 signin 페이지
6.4 signup-verify.html 구성
- 상단 공통: 언어·국가 선택 — §2.3
- 로고
- 제목: “Verify your email” (영문)
- 안내: “Enter the 6-digit code sent to {{email}}” (영문)
- 6자리 OTP 입력 UI (client-web
OtpDigitBoxes와 동일한 6칸 박스) - “Resend code” 링크 (영문)
- 오류 메시지 영역
6.5 OTP 입력 UI (Vanilla JS)
client-web의 otp-digit-boxes.tsx 로직을 참조:
- 6개 input,
inputMode="numeric",maxLength=6 - paste 지원 (숫자만 추출)
- 6자리 완성 시 자동으로
onComplete콜백 autocomplete="one-time-code"
7. API 호출 정리
7.1 이메일 OTP
| API | Method | Body | 응답 |
|---|---|---|---|
/auth/email/send-otp | POST | { email } | { success: true } |
/auth/email/verify-otp | POST | { email, code } | { success: true, user } + Set-Cookie (JWT) |
7.2 Google
| API | Method | 동작 |
|---|---|---|
/auth/google | GET | return_url 쿼리로 리다이렉트 URL 전달 → Google OAuth로 이동 |
/auth/google/callback | GET | OAuth 콜백 → JWT 발급 후 return_url로 리다이렉트 |
8. 네비게이션 및 라우팅
| 위치 | 링크 | 대상 |
|---|---|---|
| index.html 헤더 | ”회원가입” | signup.html |
| index.html 헤더 | ”로그인” | index.html (Step 2) |
| signup.html | ”이미 계정이 있으신가요?“ | index.html |
| index.html Step 2 | ”Google로 계속하기” | /auth/google |
| signup.html | ”Google로 간편 가입” | /auth/google |
9. 환경 변수
9.1 www (클라이언트)
window.PREGO_AUTH_URL = 'https://{zuplo-domain}'; // Zuplo Auth API 베이스9.2 Zuplo
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REDIRECT_URIJWT_SECRET,CONTROL_PLANE_URL,INTERNAL_API_KEYRESEND_API_KEY(이메일 발송) 또는 Zuplo POST /email 호출 시ZUPLO_EMAIL_API_KEY
10. 구현 우선순위
| 순서 | 작업 | 설명 |
|---|---|---|
| 1 | 기본 영문화 | 모든 www 페이지 UI를 영문으로 통일 |
| 2 | 상단 locale UI | 헤더에 Language·Country 선택 추가, localStorage/쿠키 저장 |
| 3 | signup.html | 이메일 입력 폼, Google 버튼, API 연동 (영문) |
| 4 | signup-verify.html | 6자리 OTP 입력, verify API 연동 (영문) |
| 5 | api.js | sendEmailOtp, verifyEmailOtp, getGoogleAuthUrl (확인·보완) |
| 6 | index.html | 회원가입 링크, Step 2 Google 버튼, 영문 UI |
| 7 | Cloudflare geo | CF-IPCountry 활용 국가 파악 로직 (Workers/엣지 또는 클라이언트) |
| 8 | 브라우저 언어 | navigator.language 기반 기본 언어 감지 (향후 다국어용) |
| 9 | styles.css | signup·verify, locale 선택 UI 스타일 |
| 10 | 테스트 | 이메일 OTP E2E, Google OAuth E2E, locale 동작 |
11. 참조 코드 위치
| 항목 | 경로 |
|---|---|
| client-web 회원가입 | apps/client-web/app/signup/page.tsx |
| client-web OTP 검증 | apps/client-web/app/[companyId]/[lang]/auth/verify-email/page.tsx |
| OTP 6자리 UI | apps/client-web/components/passcode/otp-digit-boxes.tsx, code-entry-form.tsx |
| Zuplo OTP request | prego-zuplo/config/00-security.oas.json → /auth/otp/request |
| Zuplo 메일 API | prego-zuplo/config/25-email.oas.json → POST /email |
| Zuplo Auth (www용) | prego-zuplo/config/05-auth.oas.json, modules/auth-handler.ts |
| www 기존 Step 2 | apps/www/index.html, app.js |
12. 검증 체크리스트
- 모든 www 페이지가 영문으로 표시됨 (index, signup, signup-verify, dashboard, billing, app.js, api.js)
- 상단에 언어·국가 선택 UI가 노출됨 (locale.js, 모든 페이지 헤더)
- Cloudflare 배포 시
CF-IPCountry등으로 접속 국가 파악 가능 (functions/api/country.js, locale.js) - 브라우저 언어가 저장·우선 적용될 수 있는 구조 (locale.js getEffectiveLocale)
- signup.html에서 이메일 입력 → “Send verification code” → 이메일 수신 (PREGO_AUTH_URL·Zuplo 연동 후 E2E 검증)
- signup-verify.html에서 6자리 입력 → 검증 성공 → JWT 쿠키 설정 (E2E 검증)
- “Google로 간편 가입” 클릭 → Google 로그인 → 콜백 후 www 복귀 및 로그인 상태 (E2E 검증)
- index.html Step 2 “Google로 계속하기” 동작 (app.js, getGoogleAuthUrl)
- CORS·credentials 설정으로 www 도메인에서 Zuplo API 호출 가능 (배포 환경별 검증)