Skip to content

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설명
1signupPOST /auth/otp/request이메일 입력 후 인증코드 발송 요청
2verify-emailPOST /auth/otp/verify6자리 코드 입력 후 검증

관련 파일:

  • apps/client-web/app/signup/page.tsx: 이메일 폼, handleSubmitPOST /auth/otp/request { email, lang }
  • apps/client-web/app/[companyId]/[lang]/auth/verify-email/page.tsx: CodeEntryForm (6자리 OTP), handleSuccessPOST /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.html6자리 OTP 입력 → 검증 후 계정 생성/로그인
Google 간편가입(버튼)/auth/google 리다이렉트 → 콜백 후 로그인

4.2 이메일 OTP 플로우

  1. 사용자가 signup.html에서 이메일 입력 후 “인증코드 받기” 클릭
  2. POST /auth/email/send-otp 호출 ({ email })
  3. Zuplo auth-handler:
    • 6자리 OTP 생성
    • Control Plane POST /internal/auth/create-otp로 D1 저장
    • 이메일 발송: Zuplo POST /email 또는 Resend API
  4. 성공 시 signup-verify.html?email=...로 이동 (또는 sessionStorage에 email 저장 후 이동)
  5. signup-verify.html에서 6자리 코드 입력
  6. POST /auth/email/verify-otp 호출 ({ email, code })
  7. 성공 시 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 플로우

  1. signup.html 또는 index.html Step 2에 “Google로 계속하기” 버튼
  2. 클릭 시 window.location.href = PREGO_AUTH_URL + '/auth/google?return_url=' + encodeURIComponent(returnUrl)
  3. Zuplo /auth/google → Google OAuth 화면으로 리다이렉트
  4. 사용자 동의 후 /auth/google/callback 호출
  5. auth-handler: 토큰 교환 → 사용자 정보 조회 → D1 users upsert → JWT 발급 → return_url로 리다이렉트 (Set-Cookie: PREGO_JWT)

5.2 연동 페이지

  • signup.html: “Google로 간편 가입” 버튼
  • index.html Step 2 (로그인): 기존 “Google로 계속하기” 버튼 유지

5.3 환경 변수 (이미 설정된 것으로 가정)

  • GOOGLE_CLIENT_ID
  • GOOGLE_CLIENT_SECRET
  • GOOGLE_REDIRECT_URI (예: https://{zuplo-domain}/auth/google/callback)

6. www 신규·수정 파일

6.1 신규 페이지

파일설명
signup.html회원가입 진입: 이메일 입력, Google 버튼
signup-verify.html6자리 OTP 입력 (client-web verify-email 패턴)

6.2 수정 파일

파일수정 내용
index.html상단 언어·국가 선택 UI 추가; “Sign up” 링크 → signup.html; 모든 UI 영문
api.jssendEmailOtp, verifyEmailOtp, getGoogleAuthUrl (이미 존재 시 확인)
styles.csssignup·verify 페이지용 스타일; 상단 locale 선택 UI 스타일
_headers 또는 WorkersCloudflare 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

APIMethodBody응답
/auth/email/send-otpPOST{ email }{ success: true }
/auth/email/verify-otpPOST{ email, code }{ success: true, user } + Set-Cookie (JWT)

7.2 Google

APIMethod동작
/auth/googleGETreturn_url 쿼리로 리다이렉트 URL 전달 → Google OAuth로 이동
/auth/google/callbackGETOAuth 콜백 → 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_URI
  • JWT_SECRET, CONTROL_PLANE_URL, INTERNAL_API_KEY
  • RESEND_API_KEY (이메일 발송) 또는 Zuplo POST /email 호출 시 ZUPLO_EMAIL_API_KEY

10. 구현 우선순위

순서작업설명
1기본 영문화모든 www 페이지 UI를 영문으로 통일
2상단 locale UI헤더에 Language·Country 선택 추가, localStorage/쿠키 저장
3signup.html이메일 입력 폼, Google 버튼, API 연동 (영문)
4signup-verify.html6자리 OTP 입력, verify API 연동 (영문)
5api.jssendEmailOtp, verifyEmailOtp, getGoogleAuthUrl (확인·보완)
6index.html회원가입 링크, Step 2 Google 버튼, 영문 UI
7Cloudflare geoCF-IPCountry 활용 국가 파악 로직 (Workers/엣지 또는 클라이언트)
8브라우저 언어navigator.language 기반 기본 언어 감지 (향후 다국어용)
9styles.csssignup·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자리 UIapps/client-web/components/passcode/otp-digit-boxes.tsx, code-entry-form.tsx
Zuplo OTP requestprego-zuplo/config/00-security.oas.json/auth/otp/request
Zuplo 메일 APIprego-zuplo/config/25-email.oas.json → POST /email
Zuplo Auth (www용)prego-zuplo/config/05-auth.oas.json, modules/auth-handler.ts
www 기존 Step 2apps/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 호출 가능 (배포 환경별 검증)
Help