1주차 — 감 잡기
17. 정리
위임한다는 건 책임이 사라지는 게 아니라 위치가 바뀌는 것이다
전체 그림 되짚기
섹션 제목: “전체 그림 되짚기”flowchart TB
U["사용자"]
U --> V["Vercel — 실행 계층<br/>렌더링 · 라우팅 · 요청 단위 서버 코드"]
U -.->|"직접 연결"| S
subgraph S["Supabase — 상태 계층"]
direction LR
A["Auth<br/>JWT 발급"]
P[("Postgres + RLS")]
ST["Storage"]
RT["Realtime"]
EF["Edge Functions"]
A --> P
ST --> P
RT --> P
EF --> P
end
V --> S
classDef key fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef mute fill:#f1f5f9,stroke:#94a3b8,color:#334155
class P key
class U,V,A,ST,RT,EF mute
한 문장: Auth가 발급한 JWT를 Postgres의 RLS가 해석해서 행 단위로 접근을 판정한다. 나머지는 전부 그 위에 얹힌 편의 기능이다.
꼭 기억할 10가지
섹션 제목: “꼭 기억할 10가지”- Supabase를 배우는 건 Postgres를 배우는 것이다
- 테이블 생성과
enable row level security는 한 세트다 publishable key는 공개해도 되고,secret key는 절대 안 된다auth.uid()는 JWT의sub이고, RLS의 입력이다user_metadata는 사용자가 고칠 수 있다 — 권한 판단에 쓰지 않는다- RLS 성능 3종: 역할 명시 ·
(select auth.uid())· 인덱스 - Vercel은 실행, Supabase는 상태. 리전은 맞춘다
- 스키마의 진실은
supabase/migrations/, 대시보드가 아니다 - 서버에서 신원 확인은
getClaims(),getSession()은 신뢰하지 않는다 - 원자성이 필요하면 RPC로 묶는다
장별 한 줄 요약
섹션 제목: “장별 한 줄 요약”| 장 | 한 줄 |
|---|---|
| 1 왜 Supabase | BaaS는 포장이고 알맹이는 Postgres다. 나갈 길이 있다는 게 차별점 |
| 2 아키텍처 | 모든 부품이 하나의 Postgres를 공유한다. 키는 두 개면 된다 |
| 3 시작하기 | 대시보드는 탐색용. 진실은 migrations/. db reset이 통과해야 커밋 |
| 4 Postgres | profiles 패턴 · timestamptz · 외래 키에는 인덱스를 직접 |
| 5 Data API | SQL이 아니라 HTTP다. 경계를 넘으면 뷰 또는 RPC |
| 6 Auth | JWT를 발급한다. app_metadata만 권한 판단에 쓴다 |
| 7 RLS | 자동으로 붙는 WHERE 절. using(기존 행) / with check(새 값) |
| 8 Storage | 파일도 테이블이다. 경로 설계가 곧 권한 설계 |
| 9 Realtime | 셋이다. 규모가 커지면 Broadcast from Database로 |
| 10 Edge Functions | 시크릿이 필요한 코드의 자리. 함수 URL은 공개되어 있다 |
| 11 확장 | 인프라를 늘리지 않고 기능이 는다. pgvector · pg_cron · pgmq |
| 12 역할 배분 | Vercel은 실행, Supabase는 상태. 리전을 맞춘다 |
| 13 Next.js | @supabase/ssr + 클라이언트 4종. 미들웨어는 UX, 방어선은 RLS |
| 14 운영 | db reset이 재현성을 보증한다. 복구해 본 적 있어야 백업 |
| 15 성능·비용 | 인덱스가 대부분을 푼다. 조용한 킬러는 대역폭 |
| 16 실전 패턴 | 헬퍼 함수로 정책을 추출한다. 웹훅은 멱등하게 |
첫 프로젝트 시작 순서
섹션 제목: “첫 프로젝트 시작 순서”-
supabase init→supabase start— 로컬 스택부터 띄운다 -
첫 마이그레이션에
profiles테이블 + 트리거 + RLS를 작성한다 -
supabase db reset으로 재현성 확인 -
supabase gen types typescript --local을package.json스크립트로 등록 -
Next.js에
@supabase/ssr클라이언트 4종(브라우저/서버/미들웨어/관리자) 세팅 -
로그인 → 보호된 페이지 → 데이터 CRUD 한 사이클을 끝까지 만들어 본다
-
원격 프로젝트 생성 →
supabase link→ CI에서db push -
Vercel 연결, 환경 변수 3종 세팅, Redirect URL 등록
-
Security Advisor 경고 0개 확인
-
배포
6번을 건너뛰고 기능을 넓히지 말 것. 한 사이클이 완결되면 나머지는 반복이다.
학습 로드맵
섹션 제목: “학습 로드맵”1개월차 — 실전 구조
3개월차 — 운영 감각
자주 받는 질문
섹션 제목: “자주 받는 질문”Prisma나 Drizzle을 같이 써도 되나? 된다. 다만 직접 연결에는 RLS가 적용되지 않으니, 서버 전용 경로로 한정하고 사용자 데이터 접근은 Data API로 하는 조합이 안전하다.
RLS가 너무 어렵다. 그냥 서버에서 처리하면 안 되나? 가능하다. 하지만 그러면 모든 접근 경로에 검증 코드를 복제해야 한다. 경로가 하나뿐(서버 API만)이라면 합리적인 선택일 수 있다.
Free 플랜으로 서비스를 운영해도 되나? 1주일 비활동 시 일시정지되고 자동 백업이 없다. 실사용자가 있으면 최소 Pro를 권한다.
셀프호스팅이 현실적인가? 가능하지만 Postgres 운영 경험이 필요하다. 대부분의 팀에는 관리형이 더 저렴하다.
참고 자료
섹션 제목: “참고 자료”공식
같이 보면 좋은 것
PostgREST 문서 — Data API의 실체를 이해하는 데 도움된다
Postgres 공식 문서 — RLS, 인덱스, explain 부분
Next.js 문서 — App Router의 캐싱과 동적 렌더링
마지막으로
섹션 제목: “마지막으로”Supabase의 가치는 “백엔드를 안 만들어도 된다”가 아니라 **“백엔드의 반복되는 부분을 데이터베이스에 위임하고 정말 중요한 로직에 집중할 수 있다”**는 데 있다.
- 위임한다는 건 책임이 사라지는 게 아니라 위치가 바뀌는 것이다
- 그 새 위치가 RLS 정책과 마이그레이션 파일이다