Supabase 완전 정복 시리즈 1편 — Supabase란 무엇인가? Firebase와 제대로 비교해보기




시리즈 목차 1편 👉 Supabase란 무엇인가? Firebase와 제대로 비교해보기 (현재 글) 2편 – 데이터베이스 & 자동 API (REST/GraphQL) 3편 – 인증(Auth) — 소셜 로그인, JWT, SSO, SAML 4편 – RLS 보안 — Row Level Security 완벽 가이드 …


들어가며

백엔드 없이 서비스를 만들고 싶다면, 요즘 개발자들이 가장 먼저 떠올리는 두 가지 선택지가 있습니다. 바로 FirebaseSupabase입니다.

Firebase는 2011년 등장해 구글에 인수된 이후 오랫동안 BaaS(Backend as a Service)의 대명사였습니다. 수많은 스타트업이 Firebase 위에서 빠르게 MVP를 만들고 성장했죠. 그런데 2020년, 조용히 등장한 Supabase가 개발자 커뮤니티에서 점점 더 큰 주목을 받기 시작했습니다.

“Firebase 대안” 을 자처하며 등장한 Supabase는, 이제 단순한 대안이 아니라 독자적인 생태계를 갖춘 프로덕션급 플랫폼으로 성장했습니다. 이 글에서는 Supabase가 무엇인지, Firebase와 어떻게 다른지, 그리고 어떤 상황에서 Supabase를 선택해야 하는지 꼼꼼하게 살펴봅니다.


Supabase란?

Supabase는 오픈소스 Firebase 대안을 표방하는 Backend as a Service 플랫폼입니다. 핵심은 PostgreSQL입니다. Supabase는 Postgres를 중심으로, 개발자가 백엔드를 구성하는 데 필요한 모든 것을 하나의 플랫폼에서 제공합니다.

공식 슬로건처럼 “The Postgres development platform” — Supabase는 Postgres를 기반으로 웹, 모바일, AI 애플리케이션을 구축하기 위한 플랫폼입니다.

Supabase가 제공하는 핵심 기능을 한눈에 보면:

기능설명
Database전용 PostgreSQL 데이터베이스
Auth이메일, 소셜 로그인, SSO, MFA 등
REST / GraphQL APIDB 테이블 기반 자동 API 생성
RealtimeWebSocket 기반 실시간 데이터 구독
StorageS3 호환 파일/이미지 스토리지
Edge FunctionsDeno 기반 서버리스 함수
Vector / AIpgvector 확장, Vector Buckets
Cron & Queues백그라운드 작업 자동화

이 모든 기능이 하나의 프로젝트 대시보드에서 관리됩니다.


Firebase란?

Firebase는 Google이 운영하는 완전 관리형 BaaS 플랫폼입니다. 2011년 실시간 데이터베이스로 시작해 현재는 인증, 스토리지, 서버리스 함수, 분석, 푸시 알림 등 광범위한 서비스를 제공합니다.

Firebase의 핵심 데이터베이스는 Cloud Firestore로, JSON 도큐먼트 형태로 데이터를 저장하는 NoSQL 데이터베이스입니다. 실시간 동기화가 DNA에 새겨진 플랫폼답게, 모바일 앱 특히 Android/iOS 개발에 최적화되어 있습니다.


가장 큰 차이: SQL vs NoSQL

Supabase와 Firebase의 근본적인 차이는 데이터베이스 패러다임에서 시작됩니다.

Firebase (NoSQL — Firestore)

// Firestore 도큐먼트 예시
{
  "users": {
    "user_abc123": {
      "name": "김철수",
      "email": "kim@example.com",
      "orders": ["order_1", "order_2"]
    }
  }
}
  • 스키마가 없어서 초기 프로토타이핑이 빠릅니다.
  • 컬렉션/도큐먼트 구조로 데이터를 저장합니다.
  • 복잡한 조인 쿼리가 어렵고, 관계형 데이터를 표현하려면 데이터를 중복 저장(비정규화)해야 합니다.
  • 쿼리 제약이 있어 복잡한 필터링은 클라이언트에서 처리해야 하는 경우가 많습니다.

Supabase (SQL — PostgreSQL)

-- Supabase PostgreSQL 예시
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE orders (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES users(id),
  total NUMERIC,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
  • 외래 키, 인덱스, 트랜잭션을 기본으로 지원합니다.
  • 복잡한 JOIN, 집계 함수, 서브쿼리 모두 SQL로 처리합니다.
  • 스키마를 미리 정의하기 때문에 데이터 무결성이 보장됩니다.
  • 어떤 백엔드 개발자든 SQL을 알면 즉시 익힐 수 있습니다.

기능별 상세 비교

1. 데이터베이스

항목SupabaseFirebase
데이터 모델관계형 (PostgreSQL)도큐먼트 (NoSQL)
쿼리 언어SQLFirestore 전용 쿼리
복잡한 JOIN✅ 완벽 지원❌ 미지원
트랜잭션✅ ACID 보장⚠️ 제한적
스키마명시적 정의스키마리스
오프라인 지원⚠️ 제한적✅ 우수

2. 인증 (Auth)

두 플랫폼 모두 이메일/비밀번호, 소셜 로그인(Google, GitHub 등), 전화/SMS 인증, MFA를 지원합니다. 차이점은 보안 모델에 있습니다.

  • Firebase: JavaScript 유사 문법의 Security Rules로 접근 제어
  • Supabase: PostgreSQL Row Level Security(RLS)로 DB 레벨에서 접근 제어. SQL을 안다면 훨씬 강력하고 직관적입니다.

3. 실시간 (Realtime)

  • Firebase: 실시간이 DNA. 별도 설정 없이 즉각적인 동기화
  • Supabase: PostgreSQL Replication Log를 WebSocket으로 변환. 테이블을 직접 구독하는 방식으로, 약간의 설정이 필요하지만 SQL 기반이라 제어가 용이함

4. 가격 정책

Firebase는 읽기/쓰기 횟수 기반 과금이라, 잘못된 쿼리 하나가 예상치 못한 청구서를 만들 수 있습니다. 반면 Supabase는 스토리지 크기 + 사용량 기반으로, 훨씬 예측 가능합니다.

플랜SupabaseFirebase
무료500MB DB, 5GB 스토리지Spark 플랜 (제한 있음)
유료 시작$25/월 (Pro)사용량 기반 (Blaze)
과금 방식예측 가능한 정액+초과읽기/쓰기당 과금

5. 오픈소스 & 벤더 락인

이것이 많은 개발자가 Supabase로 이동하는 핵심 이유 중 하나입니다.

  • Firebase: 완전 프로프라이어터리. Google 생태계에 종속됩니다. (Google이 서비스를 종료한 전례가 있다는 점을 기억하세요.)
  • Supabase: 100% 오픈소스. Docker로 셀프 호스팅이 가능합니다. 언제든지 AWS, DigitalOcean, 또는 자체 서버로 이전할 수 있습니다.

Next.js에서 Supabase 시작하기

이론은 충분합니다. 코드로 확인해봅시다. Next.js App Router + TypeScript 환경에서 Supabase를 세팅하는 방법을 살펴봅니다.

1. 설치

npx create-next-app@latest my-app --typescript --app
cd my-app
npm install @supabase/supabase-js @supabase/ssr

2. 환경 변수 설정

Supabase 대시보드 → Project Settings → API에서 URL과 키를 확인합니다.

# .env.local
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

3. Supabase 클라이언트 생성

App Router 환경에서는 Server Component용Client Component용 클라이언트를 분리해서 만들어야 합니다.

// lib/supabase/client.ts — 클라이언트 컴포넌트용
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}
// lib/supabase/server.ts — 서버 컴포넌트용
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // Server Component에서 호출 시 무시
          }
        },
      },
    }
  )
}

4. 미들웨어 설정

세션을 자동으로 갱신하려면 middleware.ts가 필요합니다.

// middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  let supabaseResponse = NextResponse.next({ request })

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) =>
            request.cookies.set(name, value)
          )
          supabaseResponse = NextResponse.next({ request })
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  // 세션 갱신 (중요: 이 줄을 반드시 포함해야 합니다)
  await supabase.auth.getUser()

  return supabaseResponse
}

export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}

5. 데이터 조회 예시 (Server Component)

// app/page.tsx
import { createClient } from '@/lib/supabase/server'

export default async function HomePage() {
  const supabase = await createClient()

  const { data: posts, error } = await supabase
    .from('posts')
    .select('id, title, created_at')
    .order('created_at', { ascending: false })
    .limit(10)

  if (error) {
    console.error(error)
    return <div>데이터를 불러오지 못했습니다.</div>
  }

  return (
    <main>
      <h1>최신 포스트</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  )
}

Server Component에서 await으로 서버사이드 데이터 패칭이 이렇게 간단합니다.


언제 Supabase를 선택해야 할까?

✅ Supabase가 맞는 경우

  • 관계형 데이터 구조가 필요한 서비스 (e커머스, SaaS, 대시보드 등)
  • SQL을 잘 아는 팀, 또는 SQL을 배우고자 하는 팀
  • 오픈소스, 셀프 호스팅, 벤더 락인 회피가 중요한 경우
  • AI 기능(벡터 검색, 임베딩)을 DB와 통합하고 싶은 경우
  • Next.js, React 등 웹 프레임워크 기반 개발
  • 예측 가능한 인프라 비용이 중요한 스타트업

✅ Firebase가 맞는 경우

  • Android/iOS 네이티브 앱 개발 (특히 Flutter)
  • 실시간 동기화가 핵심인 채팅, 게임, 스코어보드
  • 푸시 알림(FCM)이 필수인 앱
  • Google 생태계(Analytics, AdMob, Crashlytics)와 깊은 통합이 필요한 경우
  • 스키마 없이 빠르게 프로토타이핑하고 싶은 경우

마치며

Supabase는 더 이상 “Firebase 대안” 수준에 머물지 않습니다. PostgreSQL의 강력함을 그대로 활용하면서, BaaS의 편의성을 누릴 수 있는 성숙한 플랫폼으로 성장했습니다.

특히 Next.js + TypeScript 조합으로 웹 서비스를 개발하는 개발자라면, Supabase는 현재 가장 강력한 백엔드 선택지 중 하나입니다. SQL의 표현력, 오픈소스의 자유로움, 그리고 날로 확장되는 AI 기능까지 — 이 시리즈를 통해 Supabase의 모든 것을 하나씩 파헤쳐 보겠습니다.

다음 편에서는 Supabase의 핵심인 PostgreSQL 데이터베이스와 자동 생성 API(REST/GraphQL) 를 Next.js에서 실전으로 다뤄봅니다.




댓글 남기기