구현 업데이트 (2025): /trial 은 Pages Functions 프록시 없이 브라우저가 NEXT_PUBLIC_ZUPLO_API_URL 로 Zuplo에 직접 POST /api/trial/* 합니다. NEXT_PUBLIC_TRIAL_USE_SAME_ORIGIN, 저장소 functions/_shared/trial-zuplo-proxy.js 는 제거됨. 운영 체크리스트는 API gateway & BFF governance 및 www /trial Zuplo 통합 기획을 따르세요.
0. 문서 목적·비범위
1. 무료 이메일 주소 서비스 필터링 — 2단계 외부 라이브러리
1.1 요구사항 정리
1.2 패키지 계약 (npm)
- 설치:
npm i free-email-domains-list — npm: free-email-domains-list.
- 라이선스: MIT. 도메인 목록은 커뮤니티 유지 gist 기반이며 주간 갱신을 전제로 한다(패키지 README).
- 공개 API:
isFreeEmail(email), isCompanyEmail(email) — 이메일이 유효한 형식이 아니면 false. 옵션 IsEmailOptions는 validator 기반이며, 패키지는 validator를 peer dependency 로 둔다.
- 번들 크기: npm 기준 압축 해제 약 2MB 수준(도메인 상수 포함). prego-control-plane(Cloudflare Worker)에 넣을 때는 Worker 번들 한도·콜드 스타트를 구현 전에 측정하고, 필요 시 도메인만 추출한 경량 세트 또는 KV/R2 등 외부 적재로 분리할지 기획 단계에서 결정한다.
1.3 구현 시 고려사항 (Worker·파이프라인)
| 항목 | 내용 |
|---|
| 적용 레이어 | prego-control-plane 의 POST /v1/trial/email/check (및 내부 preview) 분류 파이프라인 서버 측에서만 isFreeEmail / isCompanyEmail(또는 패키지가 노출하는 도메인 집합)을 사용한다. |
| www / 브라우저 | 대량 도메인 리스트를 클라이언트에 내려보내지 않는다. |
| Zuplo | 비즈니스 규칙은 게이트웨이가 아닌 CP 에 둔다(tenant trust). |
| validator peer | CP package.json에서 peer 충족 및 Worker 런타임과의 호환을 구현 시 확인한다. |
| 기존 phase2 | Abstract Email Validation 등 옵션 phase2 가 있으면, npm 판별과의 순서·중복 호출·reasonCode 를 설계에 명시한다. |
1.4 관리자 UI·D1 dictionary
- 기존: 커스텀 무료메일 도메인(또는 예외) 등록·조회·로그 화면은 그대로 “운영자 주도 커스텀 목록” 으로 둔다.
- 신규/변경 없음:
free-email-domains-list 내장 목록을 관리자 화면에서 편집하는 흐름은 두지 않는다(필요 시 패키지 버전·갱신 주기만 읽기 전용 표시 정도는 선택 사항).
1.5 계약·관측
- 응답 JSON의
reasonCode, pipeline, phase2_json 등 기존 필드에 free-email-domains-list 기반 매칭을 반영할지 정한다.
- 회귀 테스트: 알려진
gmail.com, 기업 도메인, 커스텀 등록 도메인 케이스.
2. ‘Email verification isn’t available on this site yet…’ 원인·해결안
2.1 원인 (현재 코드·배포 기준)
- 해당 문구는
TRIAL_EMAIL_GATEWAY_NOT_CONFIGURED_COPY 로, TrialEmailGate 가 isTrialEmailGatewayConfigured() === false 일 때 페이지 진입 직후 노출된다.
apps/www/lib/trial-gateway.ts (현행):
NEXT_PUBLIC_TRIAL_GATEWAY_CONFIGURED=1 이면 항상 “구성됨”.
- 그렇지 않으면
NEXT_PUBLIC_ZUPLO_API_URL 이 빌드에 있어야 구성됨 (비어 있으면 배너 + 입력 비활성).
- 브라우저는 Zuplo 호스트로 직접
POST /api/trial/email/check 등을 호출한다. Pages Functions 트라이얼 프록시는 사용하지 않음.
2.2 해결안 (운영)
- Cloudflare Pages (또는 빌드 파이프라인) Build 환경 변수:
NEXT_PUBLIC_ZUPLO_API_URL = Zuplo 베이스 (끝 슬래시 없음).
- prego-zuplo CORS /
ALLOWED_ORIGINS 에 www 프로덕션·프리뷰 오리진 포함 (트라이얼 라우트는 게이트웨이에서 허용 범위가 넓지만, 운영 정책은 runbook과 일치시킬 것).
- 재빌드·재배포 (정적 export →
NEXT_PUBLIC_* 는 번들에 박힘).
2.3 검증 체크리스트
3. /trial 페이지 레이아웃 — 첫 화면에서 푸터(하단 라인) 비노출
3.1 요구사항
- PC·모바일 스크린 크기 기준, 첫 뷰포트(스크롤 없음) 에서 페이지 하단 푸터(또는 “bottom 라인”)가 보이지 않게 한다.
- 이를 위해 메인 콘텐츠 영역의 최소 높이를 키워 헤더 아래 영역이 뷰포트를 채우고, 푸터는 스크롤 시에만 노출되게 한다.
3.2 현재 구조 (기획용)
TrialPageClient: 최상위 min-h-screen + flex column, main 은 flex-1 + justify-center 로 폼을 세로 중앙 정렬, 하단에 Footer .
- 뷰포트가 높을 때는 폼이 중앙에만 있고 푸터가 같은 화면 하단에 보이는 전형적인 레이아웃이 되어, “첫 화면에 푸터를 숨김” 요구와 충돌할 수 있다.
3.3 설계 방향
| 항목 | 제안 |
|---|
| 높이 단위 | 100dvh / 100svh / min-h-[calc(100dvh-<header>)] 등으로 주소창·모바일 뷰포트 변동을 고려 |
| 레이아웃 | 헤더 높이를 빼고 main 최소 높이 = 1 뷰포트 − 헤더` 를 보장해, 문서 전체 높이 ≥ 100vh 가 되도록 하여 푸터를 첫 스크롤 영역 밖으로 밀기 |
| 폼 정렬 | main 내부는 flex + items-center + justify-center 유지 가능; 다만 세로 중앙이 아니라 약간 위쪽이 브랜드에 맞으면 justify-start + pt-* 로 조정 가능 |
| 접근성 | 푸터는 스크롤로 도달 가능해야 하며, 영구 숨김이 아님 |
3.4 시각 회귀
- 대표 뷰포트: 375×812, 390×844, 1280×720, 1920×1080
- 다크 모드·쿠키 배너 유무(헤더 높이 변화) 시나리오
4. 작업 순서 제안
- 운영 환경 변수 점검 (섹션 2) — 증상이 즉시 해결되는지 확인.
- 레이아웃 (섹션 3) — www만 수정, 스테이징 Pages에서 시각 확인.
- CP 파이프라인 (섹션 1) —
free-email-domains-list 통합, Worker 번들·peer 의존성·phase2 순서, reasonCode, 테스트.
- Zuplo·OpenAPI 변경이 필요 없으면 prego-zuplo 변경 없음; CP API 동작만 확장.
5. 관련 문서·외부 참조