한 줄 요약
Borderless 베타를 ‘로그인 가능한 화면’에서 ‘운영 가능한 플랫폼’으로 확장한 설계, 구현, 배포, 장애 해결 기록입니다. 55문항 해외 진출 준비도 진단은 누구나 시작할 수 있게 두고, 결과 저장·재방문·조직 데이터 관리가 필요한 순간에 인증을 연결했습니다.
운영 서비스: https://global-gtm.vercel.app
소개
기존 Borderless는 비밀번호 없는 이메일 링크 중심의 비공개 베타였습니다. 진단 기능은 있었지만 회원가입·로그인·마이페이지·탈퇴·관리자 운영이 하나의 흐름으로 이어지지 않았고, 실제 사용자에게 테스트 링크를 전달하기에는 이메일 전달성, 결과 저장, 개인정보 보호, 운영자 권한이 충분히 닫혀 있지 않았습니다.
이번 구현의 목표는 55문항 진단은 공개로 유지하되, 결과를 저장하고 다시 보는 순간에만 인증을 요구하는 것이었습니다. 사용자의 진입 장벽을 낮추면서도 조직별 데이터와 민감정보는 안전하게 보관하고, 운영자는 실제 지표와 후속 액션을 확인할 수 있어야 했습니다.
핵심 설계 원칙
진단은 공개, 결과는 로그인 후 저장 · 코드 개발을 먼저 끝낸 뒤 운영 설정을 순차 적용 · 현재 검색 요구가 없는 phone_hash는 만들지 않음 · 보안과 데이터 손실 방지는 단순화 대상에서 제외
구현 범위
인증: 이메일·비밀번호, Google OAuth, 매직링크, 비밀번호 재설정
계정: 프로필, 필수 동의, 마케팅 동의, 탈퇴·익명화
진단: 55문항 공개 응답, 로그인 후 복원·저장
관리: 권한 SQL, 실제 지표·드릴다운, PII 마스킹·감사 로그
의도적으로 제외한 것: 앱 자체 2FA, 소셜 계정 연결 해제, 팀 초대, 유 료 구독, 진단 DB 임시저장, 이탈 추적, 전문가 자동 배정, phone_hash.
완성 기준
신규 사용자가 이메일·비밀번호, Google 또는 매직링크로 가입·로그인할 수 있다.
익명 사용자가 완료한 55개 답변이 인증 후 사라지지 않고 정확히 복원·저장된다.
전화번호는 서버에서만 암호화하고, 탈퇴 시 프로필은 익명화하며 인증 계정은 soft delete 한다.
관리자 화면은 샘플이 아니라 실제 조직·사용자·진단·주문 데이터를 조회한다.
SMTP, Google OAuth, Vercel 환경변수와 배포까지 실제 운영 경로로 검증한다.
진행 방법
Codex와 함께 Next.js 코드베이스를 분석하고 설계 문서와 작업 계획을 먼저 보강한 뒤 진행했습니다. 인증·DB·메일은 Supabase, 배포와 환경변수는 Vercel, Google 로그인 클라이언트는 Google Cloud, 발신 SMTP는 Google Workspace, 변경 이력과 검증은 GitHub PR·Vitest·Next.js build로 관리했습니다.
핵심 프롬프트(여러 차례 지시의 통합본)
기존 Global GTM 플랫폼에 회원가입·로그인·마이페이지·관리자 대시보드를 구현한다.
첨부 설계·계획 방향은 유지하되 phone_hash는 제외하고,
탈퇴 soft delete·권한 SQL·진단 복원·실제 대시보드 연결을 보강한다.
코드 개발을 먼저 완료한 뒤 Supabase·SMTP·Google OAuth·Vercel 운영 반영을 순차 진행하고,
각 단계에서 실제 이메일·비밀번호 재설정·로그인·대시보드 흐름을 검증한다.1. 익명 진단과 인증을 연결
진단 시작부터 로그인을 강제하면 이탈이 커집니다. 그래서 55문항은 공개로 유지하고, 결과 보기 시점에 답변을 sessionStorage의 pending-assessment 키로 보관했습니다. 로그인 또는 가입이 끝나면 콜백 경로에서 답변 형식과 문항 ID를 다시 검증해 저장하고, 서버 저장이 성공한 뒤에만 임시 데이터를 지웠습니다.
export const PENDING_KEY = "pending-assessment";
savePending(answers); // 결과 보기 직전 임시 보관
const answers = loadPending(); // 로그인 후 길이·ID·레벨 검증
await submit(answers);
clearPending(); // 서버 저장 성공 뒤에만 삭제2. 인증·계정·개인정보 구현
인증: 이메일·비밀번호 가입/로그인, 이메일 확인, 매직링크, 비밀번호 재설정, Google OAuth
프로필: 이름·회사·직위·휴대전화, 필수 약관·개인정보 동의 시각, 선택 마케팅 동의
전화번호: +82 형식으로 정규화한 뒤 AES-256-GCM으로 암호화하고
v1:iv:tag:ciphertext형식으로 저장phone_hash: 현재 동일 전화번호 검색·중복 판정 요구가 없어 제외
탈퇴: 프로필의 이메일·이름을 익명화하고
phone_enc를 제거한 뒤 Supabase Auth 계정을 soft delete. 주문·정산 등 보존이 필요한 기록은 유지
const { error } = await admin.auth.admin.deleteUser(user.id, true);
// true: 인증 계정 soft delete. 그 전에 프로필 PII를 익명화한다.3. 권한 SQL과 실제 관리자 대시보드
RLS만으로는 충분하지 않았습니다. profiles 테이블에 일반 UPDATE 권한이 남아 있으면 사용자가 role이나 organization_id까지 바꿀 여지가 있습니다. 따라서 사용자가 바꿀 수 있는 컬럼만 UPDATE grant로 열고, 민감 함수를 직접 실행할 수 없도록 권한을 회수했습니다.
운영자가 먼저 할 일을 보여주는 액션 목록을 차트보다 위에 배치
가입→진단→주문 퍼널, 회사 목록, 회사·사용자 드릴다운을 실제 데이터로 연결
PII는 기본 마스킹하고 해제 시 관리자·대상·시각을 감사 로그에 기록
서버 페이지네이션·필터를 사용하고 빈 상태에는 다음 행동을 안내
4. Google OAuth는 기능 플래그 뒤에서 완성
Google 버튼은 공급자 설정이 끝나기 전에 노출하지 않았습니다. NEXT_PUBLIC_GOOGLE_AUTH_ENABLED가 true일 때만 렌더링하고, Supabase 콜백을 통해 다시 애플리케이션의 /auth/callback으로 돌아오게 했습니다.
if (process.env.NEXT_PUBLIC_GOOGLE_AUTH_ENABLED !== "true") return null;
await supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: `${origin}/auth/callback?next=${encodeURIComponent(next)}`
}
});5. 운영 반영 순서
코드·SQL·테스트를 완료하고 GitHub 브랜치에서 production build 통과
Supabase migration 적용, Site URL·Redirect URL·비밀번호 최소 길이·권한 정책 확인
기본 메일 전달 문제를 진단하고 Google Workspace 맞춤 SMTP로 전환
Google Cloud에 Borderless GTM 프로젝트와 Web OAuth client를 만들고 Supabase callback URI 등록
Google OAuth 대상 유형을 외부로 두고 테스트 단계에서 프로덕션 단계로 게시
Supabase Google provider에 새 client ID·secret을 저장하고 노출된 이전 secret은 폐기
Vercel Production·Preview에
NEXT_PUBLIC_GOOGLE_AUTH_ENABLED=true적용 후 재배포실제 메일함, Google 로그인, 비밀번호 재설정, 온보딩, 대시보드까지 브라우저로 확인
배포 설정에서 기억할 값
Supabase callback:https://slufdtwiaswuphukhmov.supabase.co/auth/v1/callbackslufdtwiaswuphukhmov는 임시 파일명이 아니라 Supabase 프로젝트를 식별하는 공개 project ref입니다.
OAuth client secret, Workspace 앱 비밀번호,P
II_ENCRYPTION_KEY는 문서·스크린샷·Git에 남기지 않습니다. 노출되면 즉시 새 값을 만들고 이전 값 을 폐기합니다.
결과와 배운 점
최종 결과
비로그인 사용자는 production 홈에서 로그인 버튼을 보고, 준비도 진단은 바로 시작할 수 있습니다.
이메일·비밀번호, Google OAuth, 매직링크, 비밀번호 재설정이 동일한 Supabase 계정 체계로 동작합니다.
Google 로그인 후 정보가 부족한 사용자는 회사 정보 보완 화면을 거쳐 원래 목적지로 돌아갑니다.
첫 진단 전 대시보드는 빈 상태와 ‘무료 준비도 진단’ CTA를 보여주고, 완료 뒤에는 실제 결과를 저장합니다.
관리자는 실제 회사·사용자·진단·주문 지표와 후속 액션을 조회할 수 있습니다.
검증 결과
검증
결과
확인 범위
자동 테스트
Vitest 36개 통과
인증·계정·진단 복원·권한 관련 동작
빌드
Next.js production build 통과
서버/클라이언트 경계와 환경변수
배포
Vercel Production 배포 성공
global-gtm.vercel.app 실서비스
운영 시나리오
메일·Google 로그인·재설정·대시보드 확인
실제 브라우저·메일함·Supabase 연동
가장 크게 배운 다섯 가지
인증 기능은 코드만의 문제가 아니다. 콘솔 설정, Redirect URL, 이메일 전달성, 브라우저 세션을 한 흐름으로 봐야 한다.
OAuth 버튼은 기능 플래그로 감추면 운영 설정이 덜 된 상태를 안전하게 배포할 수 있다.
RLS가 있어도 table/column grant를 함께 점검해야 권한 상승을 막을 수 있다.
임시 답변은 성공 전 삭제하지 않는다. 로그인 성공과 진단 저장 성공은 서로 다른 사건이다.
베타에서 Gmail SMTP는 빠른 출발점이지만 발송량이 커지면 전용 트랜잭션 메일과 도메인 인증으로 옮겨야 한다.
과정 중 시행착오
Borderless 메일과 Resend 계정 메일을 혼동: 메일의 발신자·대상 서비스·링크 도메인을 먼저 확인한 뒤 Supabase Auth의 실제 재설정 메일로 흐름을 분리했습니다.
Vercel Preview Protection이 재설정 링크를 가로챔: preview 보호를 해제하고 public branch URL과 Redirect URL을 일치시켰습니다.
Workspace 앱 비밀번호의 공백: Google이 4자리씩 띄워 보여준 앱 비밀번호에서 공백을 제거한 16자리 연속 문자열을 저장해 해결했습니다.
OTP 출처 혼동: OTP 화면의 서비스명을 먼저 확인하고 Vercel 항목의 최신 6자리 코드를 사용했습니다.
OAuth secret이 스크린샷에 노출: 즉시 새 secret을 생성해 Supabase에 교체하고 이전 값을 삭제했습니다.
Google OAuth 테스트 단계의 사용자 제한: 대상 유형을 외부로 두고 프로덕션 단계로 게시해 일반 Google 계정이 접근할 수 있게 했습니다.
온보딩 체크박스 CSS 붕괴: 원인은 컴포넌트가 아니라 공통 선택자였습니다.
input:not([type="checkbox"])와.provider-form .completion-check로 한 곳에서 고쳤습니다.
.provider-form input:not([type="checkbox"]),
.provider-form textarea,
.provider-form select { width: 100%; }
.provider-form .completion-check {
display: flex;
align-items: center;
}나만의 운영 꿀팁
매 단계마다 ‘지금 로그인하는 대상이 Borderless·Google·GitHub·Vercel 중 무엇인지’를 먼저 확인합니다.
메일 문제는 발송 요청 성공보다 수신함의 발신자·링크 도메인·도착 시간을 기준으로 검증합니다.
콘솔 설정을 바꾼 뒤에는 저장 성공 메시지, 공급자 상태, 실제 authorize 302까지 각각 확인합니다.
환경변수는 Production·Preview 범위를 명시하고 재배포까지 해야 클라이언트 번들에 반영됩니다.
사용자 화면 오류는 개별 요소보다 공통 CSS·공통 콜백·공통 권한처럼 모든 경로가 지나는 지점을 먼저 찾습니다.
도움이 필요한 부분
이용약관·개인정보 처리 및 탈퇴 후 보존 범위에 대한 법률 검토
사용자 100명 이상 또는 민감 scope가 필요해질 때 Google OAuth 검증·브랜드 검토
베타 발송량 증가 전 전용 트랜잭션 메일 공급자와 SPF·DKIM·DMARC 설계
브라우저 E2E로 가입→메일→콜백→진단 복원까지 자동 회귀 테스트
앞으로의 계획
멘티·스타트업에게 운영 링크를 배포하고 가입·진단·재방문 피드백 수집
가입→진단 완료→전문가 서비스 탐색 전환율과 오류율을 운영 KPI로 추적
베타 피드백으로 온보딩 문구와 대시보드 빈 상태를 다듬고, 필요할 때만 서버 측 임시저장 도입
운영자 액션 목록과 회사 드릴다운을 실제 상담·주문 프로세스에 맞춰 확장
도움 받은 글 (옵션)
GitHub PR #3 — Conditional Google OAuth: 조건부 Google 버튼과 OAuth UI
GitHub PR #4 — Onboarding checkbox fix: 체크박스 CSS 회귀 수정
docs/specs/2026-08-04-auth-account-design.md— 인증·계정·관리자·보안 상세 설계docs/plans/2026-08-04-auth-account-admin.md— 단계별 구현·운영 반영·검증 계획