Supabase로 SaaS 백엔드 빠르게 구축하기
Firebase 대신 Supabase를 선택한 이유와, 인증·DB·스토리지를 하루 만에 세팅한 과정.
왜 Supabase인가
SaaS 백엔드를 직접 만들면 인증, DB, API, 스토리지를 각각 구축해야 한다. 빠르게 MVP를 만들려면 BaaS(Backend as a Service)가 합리적이다.
Firebase와 Supabase를 비교했다.
| 항목 | Firebase | Supabase |
|---|---|---|
| DB | NoSQL (Firestore) | PostgreSQL (관계형) |
| 쿼리 | 제한적 | SQL 풀 스펙 |
| 인증 | 강력 | 강력 |
| 가격 | 읽기/쓰기 기반 | 행 수 기반 |
| 락인 | 높음 | 낮음 (오픈소스) |
Repasta는 사용자별 콘텐츠, 변환 이력, 구독 상태 등 관계형 데이터가 많았다. Firestore의 NoSQL 구조로는 JOIN이 필요한 쿼리를 처리하기 어렵다. PostgreSQL이 필요했고, Supabase가 답이었다.
초기 세팅
Supabase 프로젝트를 만들면 PostgreSQL DB, REST API, 인증, 스토리지가 한 번에 제공된다.
npm install @supabase/supabase-js
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!
);
인증
이메일/패스워드 로그인과 Google OAuth를 설정한다. Supabase 대시보드에서 Google 클라이언트 ID를 등록하면 끝이다.
// 이메일 회원가입
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'securepassword',
});
// Google 로그인
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
});
인증 후 supabase.auth.getUser()로 현재 사용자 정보를 가져올 수 있다. JWT 토큰 관리는 Supabase 클라이언트가 자동으로 처리한다.
Row Level Security (RLS)
Supabase의 핵심 보안 기능이다. 테이블 수준에서 “누가 어떤 행에 접근할 수 있는지”를 SQL 정책으로 정의한다.
-- 사용자는 자신의 콘텐츠만 볼 수 있다
CREATE POLICY "Users can view own content"
ON contents
FOR SELECT
USING (auth.uid() = user_id);
-- 사용자는 자신의 콘텐츠만 생성할 수 있다
CREATE POLICY "Users can insert own content"
ON contents
FOR INSERT
WITH CHECK (auth.uid() = user_id);
RLS를 켜면 API 키가 노출되어도 다른 사용자의 데이터에 접근할 수 없다. 프론트엔드에서 직접 DB를 호출하는 구조에서 필수다.
실시간 구독
Supabase는 PostgreSQL의 LISTEN/NOTIFY를 활용한 실시간 구독을 지원한다.
const channel = supabase
.channel('content-changes')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'contents',
filter: `user_id=eq.${userId}`,
}, (payload) => {
console.log('새 콘텐츠:', payload.new);
})
.subscribe();
Repasta에서는 AI 변환이 완료되면 DB에 결과를 INSERT하고, 클라이언트가 실시간으로 결과를 수신한다.
Edge Functions
복잡한 비즈니스 로직은 Edge Functions로 처리한다. Deno 기반이라 TypeScript를 바로 쓸 수 있다.
// supabase/functions/transform-content/index.ts
Deno.serve(async (req) => {
const { content, targetFormat } = await req.json();
const result = await transformWithGemini(content, targetFormat);
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
);
await supabase.from('transformations').insert({
original: content,
result,
format: targetFormat,
});
return new Response(JSON.stringify(result));
});
비용
Supabase 무료 티어로 MVP를 검증하기에 충분하다.
- DB: 500MB
- 스토리지: 1GB
- Edge Functions: 50만 호출/월
- 인증: 무제한
Pro 플랜은 $25/월부터. 사용자가 늘어도 예측 가능한 비용 구조다.
정리
Supabase는 “PostgreSQL + 인증 + API”를 한 번에 제공하는 가장 실용적인 BaaS다. SQL을 쓸 줄 알면 러닝 커브가 거의 없고, RLS 덕분에 보안도 견고하다. MVP를 빠르게 만들어야 할 때 첫 번째 선택지다.