React + Supabase + Vercel로 SaaS 개발하기 완벽 가이드 | 2026
Dev C

2026년 현재, SaaS(Software as a Service) 개발에서 가장 효율적인 스택 조합은 단연 React + Supabase + Vercel입니다. 이 조합은 빠른 개발 속도, 예측 가능한 비용, 그리고 확장성까지 모두 갖춘 현대적인 풀스택 솔루션입니다.
이 글에서는 설치부터 배포까지, SaaS 프로젝트를 시작하는 데 필요한 모든 과정을 상세히 다룹니다.
왜 React + Supabase + Vercel인가?
Firebase 대신 Supabase를 선택하는 이유
2026년 Backend-as-a-Service 시장에서 Supabase가 Firebase를 추월하고 있습니다. 그 이유는 명확합니다:
| 비교 항목 | Supabase | Firebase |
|---|---|---|
| 데이터베이스 | PostgreSQL (SQL) | Firestore (NoSQL) |
| 가격 정책 | 예측 가능한 고정 요금 | 사용량 기반 (예측 어려움) |
| AI 통합 | pgvector로 임베딩 저장 | 외부 서비스 필요 |
| 오픈소스 | ✅ 셀프 호스팅 가능 | ❌ 구글 종속 |
| Row Level Security | PostgreSQL RLS 내장 | 별도 규칙 설정 필요 |
특히 pgvector 확장을 통해 AI 임베딩을 같은 데이터베이스에 저장할 수 있어, Pinecone 같은 별도 벡터 DB 없이도 AI 기능을 구현할 수 있습니다.
Vercel의 장점
- 제로 설정 배포: Git push만으로 자동 배포
- Edge Functions: 전 세계 엣지 네트워크에서 실행
- Supabase 통합: 환경 변수 자동 설정
- 프리뷰 배포: PR마다 독립적인 미리보기 환경
개발 환경 설정
1. Node.js 및 필수 도구 설치
# Node.js 20+ LTS 설치 확인
node --version
# pnpm 설치 (권장 패키지 매니저)
npm install -g pnpm
# Vercel CLI 설치
npm install -g vercel
2. 프로젝트 생성 - Vite + React + TypeScript
# Vite로 React + TypeScript 프로젝트 생성
pnpm create vite my-saas-app --template react-ts
# 프로젝트 디렉토리 이동
cd my-saas-app
# 의존성 설치
pnpm install
3. Supabase 패키지 설치
# Supabase 클라이언트 라이브러리
pnpm add @supabase/supabase-js
# 인증 UI 컴포넌트 (선택)
pnpm add @supabase/auth-ui-react @supabase/auth-ui-shared
Supabase 프로젝트 설정
1. Supabase 대시보드에서 프로젝트 생성
- supabase.com에서 계정 생성
- New Project 클릭
- 프로젝트 이름, 데이터베이스 비밀번호, 리전 선택 (한국 사용자는 Singapore 또는 Northeast Asia 권장)
2. API 키 확인
프로젝트 생성 후 Settings > API에서 다음 값을 확인합니다:
- Project URL:
https://xxxxx.supabase.co - anon/public key: 클라이언트에서 사용
- service_role key: 서버 사이드에서만 사용 (절대 노출 금지)
3. 환경 변수 설정
프로젝트 루트에 .env.local 파일 생성:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
보안 참고:
anon key는 브라우저에 노출되어도 안전합니다. Row Level Security(RLS)가 데이터를 보호하기 때문입니다.
Supabase 클라이언트 초기화
src/lib/supabase.ts
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
타입 생성 (선택이지만 강력 권장)
Supabase CLI를 사용하면 데이터베이스 스키마에서 TypeScript 타입을 자동 생성할 수 있습니다:
# Supabase CLI 설치
pnpm add -D supabase
# 타입 생성
npx supabase gen types typescript --project-id your-project-id > src/types/database.types.ts
인증 시스템 구현
1. 인증 컨텍스트 생성
src/contexts/AuthContext.tsx
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'
import { Session, User } from '@supabase/supabase-js'
import { supabase } from '../lib/supabase'
interface AuthContextType {
session: Session | null
user: User | null
loading: boolean
signOut: () => Promise<void>
}
const AuthContext = createContext<AuthContextType | undefined>(undefined)
export function AuthProvider({ children }: { children: ReactNode }) {
const [session, setSession] = useState<Session | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
// 현재 세션 가져오기
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session)
setLoading(false)
})
// 인증 상태 변화 구독
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(_event, session) => {
setSession(session)
}
)
return () => subscription.unsubscribe()
}, [])
const signOut = async () => {
await supabase.auth.signOut()
}
return (
<AuthContext.Provider value=>
{children}
</AuthContext.Provider>
)
}
export const useAuth = () => {
const context = useContext(AuthContext)
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider')
}
return context
}
2. 로그인 컴포넌트
src/components/Auth.tsx
import { Auth } from '@supabase/auth-ui-react'
import { ThemeSupa } from '@supabase/auth-ui-shared'
import { supabase } from '../lib/supabase'
export function AuthComponent() {
return (
<div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg shadow">
<Auth
supabaseClient={supabase}
appearance=
providers={['google', 'github']}
redirectTo={window.location.origin}
/>
</div>
)
}
3. OAuth 프로바이더 설정
Supabase 대시보드에서 Authentication > Providers로 이동:
- Google: GCP Console에서 OAuth 클라이언트 ID 생성
- GitHub: GitHub Settings > Developer settings > OAuth Apps에서 앱 등록
데이터베이스 설계 및 RLS
1. 테이블 생성 예시
Supabase SQL Editor에서 실행:
-- 사용자 프로필 테이블
CREATE TABLE profiles (
id UUID REFERENCES auth.users(id) PRIMARY KEY,
email TEXT NOT NULL,
full_name TEXT,
avatar_url TEXT,
subscription_tier TEXT DEFAULT 'free',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 새 사용자 가입 시 자동 프로필 생성
CREATE OR REPLACE FUNCTION handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO profiles (id, email, full_name, avatar_url)
VALUES (
NEW.id,
NEW.email,
NEW.raw_user_meta_data->>'full_name',
NEW.raw_user_meta_data->>'avatar_url'
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION handle_new_user();
2. Row Level Security 설정
-- RLS 활성화
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
-- 사용자는 자신의 프로필만 조회 가능
CREATE POLICY "Users can view own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
-- 사용자는 자신의 프로필만 수정 가능
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
실시간 기능 구현
Supabase의 강력한 실시간 구독 기능을 활용합니다:
import { useEffect, useState } from 'react'
import { supabase } from '../lib/supabase'
export function useRealtimeMessages(channelId: string) {
const [messages, setMessages] = useState<Message[]>([])
useEffect(() => {
// 초기 데이터 로드
const fetchMessages = async () => {
const { data } = await supabase
.from('messages')
.select('*')
.eq('channel_id', channelId)
.order('created_at', { ascending: true })
if (data) setMessages(data)
}
fetchMessages()
// 실시간 구독
const subscription = supabase
.channel(`messages:${channelId}`)
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: `channel_id=eq.${channelId}`
},
(payload) => {
setMessages(prev => [...prev, payload.new as Message])
}
)
.subscribe()
return () => {
subscription.unsubscribe()
}
}, [channelId])
return messages
}
Vercel 배포
1. Vercel 프로젝트 연결
# Vercel에 로그인
vercel login
# 프로젝트 연결 및 배포
vercel
2. 환경 변수 설정
Vercel 대시보드에서 Settings > Environment Variables:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
또는 Supabase Integration을 사용하면 환경 변수가 자동으로 설정됩니다.
3. 자동 배포 설정
GitHub 저장소를 Vercel에 연결하면:
- main 브랜치 푸시 → 프로덕션 배포
- PR 생성 → 프리뷰 배포 (고유 URL 제공)
SaaS 스타터 킷 활용
빠른 시작을 원한다면 Vercel의 SaaS 스타터 킷을 활용하세요:
npx create-next-app --example https://github.com/vercel/nextjs-subscription-payments
이 스타터 킷에는 다음이 포함되어 있습니다:
- ✅ Supabase 인증 (OAuth, 비밀번호 재설정)
- ✅ Stripe 결제 통합
- ✅ 구독 관리 UI
- ✅ Tailwind CSS 스타일링
- ✅ TypeScript 지원
비용 최적화 팁
Supabase 무료 티어 한도
- 500MB 데이터베이스
- 1GB 파일 스토리지
- 50,000 월간 활성 사용자
- 2GB 대역폭
비용 절감 전략
- 불필요한 실시간 구독 제거: 실시간이 필요없는 데이터는 일반 쿼리 사용
- 이미지 최적화: Supabase Storage의 transform 기능 활용
- Edge Functions 캐싱: 반복 요청에 캐시 헤더 설정
마무리
React + Supabase + Vercel 스택은 2026년 SaaS 개발의 황금 조합입니다. PostgreSQL의 안정성, 예측 가능한 가격, 그리고 빠른 배포 파이프라인이 결합되어 MVP부터 스케일업까지 하나의 스택으로 커버할 수 있습니다.
특히 AI 기능이 필수가 된 현재, pgvector를 통한 벡터 검색을 같은 데이터베이스에서 처리할 수 있다는 점은 큰 장점입니다.
시작이 반입니다. 오늘 바로 첫 SaaS 프로젝트를 만들어보세요!