전문가용 시작
이 매뉴얼은 React와 TypeScript와 React Router가 일상이고, Supabase 또는 Stripe SDK를 한두 번이라도 만져본 적 있고, Claude Code 또는 Codex로 코드를 맡겨본 적 있는 독자를 가정합니다. FSD라는 이름은 들어봤다는 정도면 충분합니다. 6레이어 의존 방향과 API 어댑터, RLS 정책 자리는 다음 섹션 architecture에서 풀어냅니다.
여기서 다루는 것은 reference 명령이 아니라 “왜 이 모양인지”입니다. 뼈대가 왜 이렇게 잡혔는지 한 번 통과한 다음 architecture로 넘어가야 그 뒤 build-and-package와 distribution이 의미 있게 읽힙니다.
풀려는 문제 한 줄
섹션 제목: “풀려는 문제 한 줄”AI에게 SaaS를 맡기면 첫 두세 프롬프트는 멀쩡하게 나옵니다. 그다음부터 구조가 흔들립니다. service_role 키가 클라이언트 번들로 새고, 같은 라우트 path 문자열이 다섯 군데에 흩어지고, RLS 정책을 Supabase Studio에서 손으로 만들고는 다음 환경에서 사라집니다. saas-base는 그 자리들에 guardrail을 박아둔 출발점입니다.
guardrail 세 개
섹션 제목: “guardrail 세 개”FSD 6레이어 + eslint-plugin-boundaries + jsx-a11y
섹션 제목: “FSD 6레이어 + eslint-plugin-boundaries + jsx-a11y”폴더 구조는 Feature-Sliced Design을 따르고, eslint-plugin-boundaries가 빌드 타임에 import 방향을 강제합니다. AI가 임의로 레이어를 가로지르면 빌드가 깨집니다. jsx-a11y가 같은 자리에서 접근성 위반을 같이 막습니다. alt 빠진 <img>, 라벨 없는 <input>이 그 자리에서 잡힙니다.
API 어댑터 SSOT
섹션 제목: “API 어댑터 SSOT”src/shared/api/server/에 어댑터 전략이 들어있습니다. 기본은 Supabase Edge Functions (supabase.functions.invoke(...)). 옵션은 Hono on Node 또는 Cloudflare 어댑터입니다. features 슬라이스는 어떤 어댑터인지 모르고 같은 인터페이스를 부릅니다. 어댑터 결정이 .claude/state/api-adapter.json에 한 번 박힌 다음에는 호출 코드를 바꾸지 않고 백엔드 런타임을 바꿀 수 있습니다.
RLS 정책 SSOT
섹션 제목: “RLS 정책 SSOT”모든 RLS 정책은 api/migrations/<timestamp>_<name>.sql에서 정의합니다. Supabase Studio의 UI에서 정책을 만들지 않습니다. git 추적이 안 되고 환경 사이 drift가 새는 자리가 거기입니다. supabase db push가 같은 SQL을 어떤 환경에 든 동일하게 박습니다.
ADR 습관
섹션 제목: “ADR 습관”되돌리기 비싼 결정은 docs/adr/에 한 장씩 쌓습니다. 라우팅 모드를 왜 marketing-app으로 잡았는지, API 어댑터를 edge-functions로 박은 근거, 가격 플랜의 monthly/annual 분기 결정. 코드는 무엇을 했는지를 보여주고, ADR은 왜 그랬는지를 보여줍니다. 다음 세션 또는 다음 사람이 들어왔을 때 결과만 보고 의도를 거꾸로 추론하는 비용을 아낍니다.
ADR 양식과 작성 시점은 docs/adr/README.md에 짧게 정리돼 있습니다.
자동화 진입점은 한 곳을 가리킨다
섹션 제목: “자동화 진입점은 한 곳을 가리킨다”Claude Code 쪽 진입점은 .claude/agents/와 .claude/skills/입니다. Codex 쪽 진입점은 저장소 루트의 AGENTS.md입니다. 두 경로 모두 결국 같은 파일 하나를 읽습니다.
AI_AUTOMATION.md. 도메인 규칙, FSD 슬라이스 매핑, SaaS 금지 패턴, 6차원 review 체크리스트, Phase 1~6 흐름이 전부 여기 모여있습니다. 두 자동화 도구의 진입점이 한 canonical 문서를 공유하기 때문에, Claude Code에서 잡힌 결정이 Codex 세션에서도 그대로 통합니다.
지금 빠져 있는 것
섹션 제목: “지금 빠져 있는 것”이 base는 솔직히 미완성인 부분이 있습니다. 매뉴얼과 랜딩은 public이지만, 템플릿 자체는 상업 라이선스 모델입니다. 그런데 결제 흐름과 구매자 webhook이 아직 안 붙었습니다. COMMERCIAL-LICENSE.md도 초안 상태고 변호사 검토가 안 끝났습니다. 실제 판매 전에는 둘 다 마무리돼야 합니다.
기술 쪽에서도 빠진 자리가 있습니다. saas-base의 src/는 phase 5(/5-customize-saas) 이전까지는 placeholder 골격만 들어있습니다. 사용자가 본인 SaaS를 박기 전까지는 라우트 트리도, 도메인 entity도, RLS 정책도 실코드가 아닙니다. 이 매뉴얼이 가르치는 건 그 빈 골격이 phase 흐름을 거치며 어떻게 채워지는지의 절차이지, saas-base 자체의 reference 코드가 아닙니다.
이 매뉴얼이 가정하지 않는 것
섹션 제목: “이 매뉴얼이 가정하지 않는 것”OS별 설치 분기, Node 버전 매니저 선택, Supabase 또는 Stripe 계정 만들기 화면 캡처, 터미널이 처음인 사람을 위한 단계별 안내는 여기 없습니다. 그쪽이 필요하면 비개발자용 매뉴얼을 봅니다. 같은 base를 다른 호흡으로 푼 짝입니다.
다음 섹션은 architecture입니다. FSD 6레이어가 어떤 의존 방향으로 묶여있는지, 라우트 SSOT와 Supabase client SSOT가 코드에서 어떻게 생겼는지, Stripe Checkout 3단 분리가 어떻게 도는지를 다이어그램 두 개와 함께 봅니다.