실제 백엔드 연결
03-first-run.md에서 pnpm dev 가 placeholder 화면을 띄우는 모습까지 확인했다면, 이 단계에서는 같은 base 가 실제 Supabase 프로젝트에 붙어 회원가입과 로그인이 정말 돌아가게 바꿉니다. 보통 30분에서 1시간 정도 걸립니다.
지금 당장 필요하지 않다면 건너뛰어도 됩니다. 다만 phase 3 (/3-analyze-saas) 이후의 컨셉 결정 자리에서 데이터 모델을 풀려면 Supabase 가 잡혀 있어야 의미가 있습니다.
1) Supabase 프로젝트 만들기
섹션 제목: “1) Supabase 프로젝트 만들기”supabase.com 대시보드에서 New project 를 누릅니다. 프로젝트 이름과 비밀번호를 정합니다. 리전은 가까운 곳을 고르세요. 한국에서는 Tokyo 또는 Singapore 가 대기 시간 면에서 무난합니다.
프로젝트 프로비저닝이 끝나면 좌측 메뉴에서 Settings → API 로 갑니다. 이 페이지에서 세 가지를 메모해 둡니다.
Project URLanon public키service_role키 (이 키는 절대 클라이언트 코드에 넣지 마세요. 뒤에서 다시 짚습니다)
같은 페이지의 좌측 위에 보이는 Project Reference ID (abcdefghijklmn 같은 모양) 도 함께 메모해 둡니다. 다음 단계에서 CLI 가 이 ID 로 프로젝트를 가리킵니다.
2) supabase link 로 프로젝트 연결
섹션 제목: “2) supabase link 로 프로젝트 연결”본인 my-saas 디렉토리에서 다음 명령을 실행합니다.
supabase login # [01-prerequisites.md] 에서 안 했다면 한 번supabase link --project-ref <project-reference-id><project-reference-id> 자리에는 위에서 메모한 ID 를 그대로 넣습니다. 처음에는 DB 비밀번호도 한 번 물어봅니다. 위 1) 단계에서 정한 비밀번호입니다.
명령이 끝나면 .supabase/ 디렉토리가 새로 생기고 그 안에 연결 정보가 박힙니다. .gitignore 가 이 디렉토리를 이미 잡고 있으니 그대로 두면 됩니다.
3) .env.local 박기
섹션 제목: “3) .env.local 박기”base 루트에 .env.example 이 있습니다. 그 파일을 복사해 .env.local 을 만듭니다.
cp .env.example .env.local.env.local 을 에디터로 열고 다음 네 줄을 본인 값으로 채웁니다.
VITE_SUPABASE_URL=https://<project-ref>.supabase.coVITE_SUPABASE_ANON_KEY=<anon-public-key>VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...VITE_API_MODE=edge-functionsVITE_ prefix 가 중요합니다. Vite 는 이 prefix 가 붙은 변수만 클라이언트 번들에 노출합니다. prefix 가 없는 변수는 빌드 자리에서 undefined 로 잡힙니다. service_role 같은 비밀이 실수로 클라이언트에 새는 자리를 prefix 가 막아줍니다.
VITE_API_MODE 는 API 어댑터를 어떤 모드로 돌릴지 결정합니다. 기본값 edge-functions 가 권장입니다. Cloudflare Workers 위에 Hono 어댑터로 돌릴 일이 생기면 그때 hono 로 바꿉니다. 이 결정은 전문가용 아키텍처 에 더 자세히 박혀 있습니다. 비개발자라면 기본값 유지로 충분합니다.
.env.local 은 .gitignore 에 들어 있어야 합니다. git status 를 한 번 쳐서 이 파일이 untracked 로 안 보이는지 확인하세요.
4) 첫 마이그레이션 적용
섹션 제목: “4) 첫 마이그레이션 적용”base 가 들고 있는 마이그레이션은 골격뿐입니다. api/migrations/ 디렉토리에 빈 자리만 박혀 있고, 본인 SaaS 도메인의 테이블 (예: subscriptions, invoices, 본인 도메인 entity) 은 phase 5 (/5-customize-saas) 의 implement-data-layer 단계에서 자동 생성됩니다. 이 자리는 fork 시 채워집니다.
지금은 인증과 세션이 동작하는지만 확인하면 충분합니다. Supabase 의 Auth 는 별도 마이그레이션 없이 프로젝트가 생긴 시점부터 켜져 있습니다.
supabase db push이 명령이 api/migrations/ 안의 SQL 파일을 모두 본인 Supabase 프로젝트에 순서대로 적용합니다. 베이스 상태에서는 적용할 마이그레이션이 거의 없어서 명령이 짧게 끝납니다. 빨간 출력이 안 보이면 정상입니다.
5) RLS 정책의 자리
섹션 제목: “5) RLS 정책의 자리”Supabase 의 모든 테이블은 기본이 default deny 입니다. RLS (Row Level Security) 가 켜진 테이블은 정책이 한 줄 박혀 있어야 어떤 사용자도 그 행을 읽거나 쓸 수 있습니다. 정책이 없으면 anon 키든 로그인한 사용자든 그 테이블에 닿지 못합니다.
이 base 의 RLS 정책은 모두 api/migrations/<timestamp>_<name>.sql 안에서 정의됩니다. Supabase Studio 의 UI 에서 정책을 만드는 자리는 쓰지 않습니다. UI 에서 만든 정책은 git 에 박히지 않아 다음 환경에서 사라지는 자리가 됩니다.
본인 SaaS 의 테이블과 정책이 phase 5 에서 자동 생성될 때 다음 모양의 SQL 이 마이그레이션 파일에 박힙니다.
alter table public.subscriptions enable row level security;
create policy "subscriptions_select_own" on public.subscriptions for select to authenticated using (auth.uid() = user_id);이 한 줄이 “로그인한 사용자는 자기 행만 select 할 수 있다” 를 강제합니다. 이 자리는 fork 시 채워집니다. 베이스를 막 받은 시점에는 본인 SaaS 의 도메인 테이블이 아직 결정되지 않아서 실제 정책이 비어 있습니다.
6) 동작 확인
섹션 제목: “6) 동작 확인”pnpm dev 를 다시 띄우고 (Ctrl+C 로 끄고 다시 pnpm dev) 브라우저에서 http://localhost:5173 을 새로고침합니다. 회원가입 화면이 placeholder 가 아니라 진짜 Supabase Auth 에 연결된 상태로 떠야 합니다.
이메일과 비밀번호로 한 번 가입을 시도합니다. Supabase 대시보드의 Authentication → Users 에서 본인 이메일로 새 행이 한 줄 들어와 있어야 정상입니다.
행이 안 보이면 09-troubleshooting.md 의 “Supabase 가입이 안 됩니다” 항목으로 갑니다. 가장 흔한 원인은 .env.local 의 VITE_SUPABASE_URL 또는 VITE_SUPABASE_ANON_KEY 가 잘못 박혀 있는 경우입니다.
7) Edge Function 시크릿 — Stripe 와 service_role
섹션 제목: “7) Edge Function 시크릿 — Stripe 와 service_role”여기는 위 3) 단계의 .env.local 과 다른 자리입니다. 클라이언트 번들에 못 나가는 비밀 (Stripe Secret key, Stripe Webhook Secret, Supabase service_role) 은 Supabase 측 인프라에 직접 박습니다.
supabase secrets set STRIPE_SECRET_KEY=sk_test_...supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_...supabase secrets listsupabase secrets list 출력에 두 키가 보이면 정상입니다. Edge Function 안에서 Deno.env.get('STRIPE_SECRET_KEY') 로 닿습니다. .env* 파일과 무관합니다.
Stripe Webhook Secret 은 phase 5 의 implement-billing 단계에서 Stripe 대시보드에서 webhook endpoint 를 등록할 때 받습니다. 그 시점까지 이 절은 비워 두어도 됩니다.
8) API 어댑터 자리 한 단락
섹션 제목: “8) API 어댑터 자리 한 단락”src/shared/api/server/ 디렉토리에 어댑터 인터페이스가 박혀 있습니다. 기본값은 Supabase Edge Functions 호출 (edge-functions) 이고, 옵션은 Hono on Node 또는 Cloudflare Workers (hono) 입니다. 같은 features 코드가 어떤 어댑터를 쓰는지 모르고 api.invoke('checkout-session', payload) 만 부릅니다.
비개발자라면 기본값 edge-functions 를 유지하는 길이 가장 손이 덜 갑니다. Supabase 한 곳에 DB, Auth, Edge Functions 가 모여 있어 다른 인프라가 더해지지 않습니다. 나중에 트래픽이 늘거나 인프라 정책이 바뀌어 Cloudflare Workers 로 옮기고 싶어지면 VITE_API_MODE 한 줄만 바꾸고 어댑터를 갈아끼우면 됩니다. 호출 코드는 한 줄도 안 건드립니다.
이 결정은 phase 4 (/4-design-saas) 의 API 어댑터 결정 자리와 같은 표를 봅니다. .claude/state/api-adapter.json 에 박힙니다.
자주 막히는 자리
섹션 제목: “자주 막히는 자리”- 401 또는 403 에러:
anon키를 다시 복사합니다. 붙여 넣을 때 끝에 공백이나 줄바꿈이 같이 따라 들어가는 경우가 흔한 원인입니다. Failed to connect to Supabase:.env.local의VITE_SUPABASE_URL에https://가 빠졌거나 끝에/가 붙은 상태. 정확히https://<ref>.supabase.co형태로 박혀 있어야 합니다.supabase db push가 권한 에러:supabase login이 만료된 상태. 다시 로그인합니다.- 그 밖의 증상은 09-troubleshooting.md 의 Supabase 항목에 모여 있습니다.
한 발 더 — 내가 말한 시나리오대로 도는지
섹션 제목: “한 발 더 — 내가 말한 시나리오대로 도는지”여기까지 오면 회원가입과 로그인이 실제 Supabase 에 닿는 모습을 봤습니다. 다음 질문은 보통 이거입니다. “내가 처음에 말로 풀었던 시나리오대로 진짜 도나?”
이 질문은 손으로 한 번씩 클릭해서 확인할 수도 있지만, 시나리오가 두 개 세 개 늘어나면 매번 다 누르기가 번거롭습니다. base에는 그 자리를 자동으로 검사해 주는 도구가 한 개 박혀 있습니다. Claude Code 에서 이렇게 부릅니다.
/test-saas이 명령은 docs/design/saas-spec.md 의 §2 “사용 시나리오” 단락을 읽습니다. 거기 적은 한 줄짜리 시나리오를 AI 가 직접 검증 코드로 변환합니다. Vitest 가 unit 자리를, Playwright 가 e2e 자리를, supabase test db 가 RLS 정책 자리를 각각 잡습니다.
결과는 익숙한 테스트 출력 그대로가 아니라 시나리오 언어로 다시 적힌 보고서로 돌아옵니다.
총 시나리오: 6개 — 5개 통과, 1개 실패
✓ 회원가입 — 이메일과 비밀번호로 새 행 생성, RLS 정책 통과✓ 로그인 — 세션 발급, /app 진입 가능✓ 가격 페이지 — Pro 플랜 선택 시 Stripe Checkout 세션 시작✗ Stripe webhook — 서명 검증 실패: secret 이 .env.local 에 있고 supabase secrets 에 없음 파일: api/functions/stripe-webhook/index.ts:14 고치는 곳: supabase secrets set STRIPE_WEBHOOK_SECRET=...실패가 한 줄 나오면 그 자리에서 같은 Claude 에게 “이거 고쳐줘” 라고 말하면 됩니다. 어디를 봐야 하는지가 보고서에 박혀 있어서 별도 설명을 다시 적어 줄 필요가 없습니다.
/test-saas 의 자세한 작동 원리 (시나리오를 어떻게 분해해서 어느 자리에 테스트 파일을 떨구는지, 정적 측 review-saas 와는 어떻게 다른지) 는 전문가용 검증 페이지에 있습니다.
데이터가 의도한 자리에 도착하는 모습까지 확인했다면 본인 SaaS 의 모양을 정하는 자리로 넘어갑니다. 05-customize-design.md 에서 브랜딩과 디자인 톤을 잡고, 그 사이에 /3-analyze-saas 와 /4-design-saas phase 가 컨셉과 라우팅, 가격, 데이터 모델을 결정합니다.