Supabase란?
PostgreSQL 기반의 오픈소스 Backend-as-a-Service(BaaS) 플랫폼이다.
Firebase와 비슷한 형태로 인증, 데이터베이스, 스토리지, 실시간 기능을 제공하지만,
SQL 데이터베이스(PostgreSQL)를 중심으로 구성되어 있어 관계형 데이터 모델링과 쿼리에 익숙한 개발자에게 적합하다.
주요 특징
1. 데이터베이스
- PostgreSQL 기반 관리형 데이터베이스.
- SQL 쿼리, 뷰, 조인, 트랜잭션, 프로시저 지원.
Row Level Security
기능 내장 → 데이터 접근 제어 정책을 DB 레벨에서 관리 가능.
2. 인증 (Auth)
- 이메일, 소셜 로그인(OAuth), Magic Link 지원.
- JWT 기반 토큰 발급.
- 서버/클라이언트 양쪽에서 인증 처리 가능.
3. 스토리지 (Storage)
- S3 호환 스토리지 제공.
- 파일 업로드, 퍼블릭/프라이빗 권한 관리 가능.
4. 실시간 (Realtime)
- PostgreSQL의 Logical Replication 기반.
- 데이터 변경을 WebSocket으로 구독 가능.
5. Edge Functions
- Deno 기반 서버리스 함수 지원.
- API 라우트, 백엔드 커스텀 로직 처리 가능.
Supabase의 장점
- SQL 기반 → 기존 PostgreSQL 사용자에게 익숙.
- 오픈소스 → 자체 호스팅 가능.
- 서버리스 → 서버 인프라 관리 불필요.
- REST, GraphQL API 자동 제공 → 별도 API 서버 없이 바로 사용.
Supabase의 한계
- Firebase Realtime Database, Firestore와 비교하면 실시간 기능은 상대적으로 제한적.
- 고성능 대용량 처리, Edge 캐싱, 글로벌 배포에서는 직접 튜닝이 필요.
- 관리형 Postgres 특성상 데이터베이스 연결 비용과 구조 최적화를 별도로 고려해야 한다.
정리
Supabase는 관계형 DB 기반의 서버리스 백엔드 플랫폼을 찾는 개발자에게 실용적인 선택지다.
Firebase처럼 클라이언트 중심이 아닌 서버, 클라이언트 모두에서 유연하게 사용할 수 있는 점이 장점이며,
특히 Next.js App Router와 같은 서버 중심 프레임워크 환경에서 사용하기 적합하다.
Supabase 시작하기
Supabase 프로젝트 생성 및 초기 설정
1. Supabase 회원가입 및 로그인
- https://supabase.com/에 접속.
- GitHub 계정으로 로그인 가능하며, 별도 계정 생성도 지원.
- 로그인 후 **Dashboard(콘솔)**에서 모든 프로젝트 관리 가능.
2. 새 프로젝트 생성
-
Supabase Dashboard 상단에서
New Project
버튼 클릭. -
원하는 프로젝트 이름 입력.
-
데이터베이스 비밀번호 설정 → Postgres 접속 시 사용할 비밀번호.
- 이 비밀번호는 나중에 Supabase에서 직접 Postgres에 접속하거나 Supabase 관리 콘솔의 SQL Editor에서 쿼리 작성 시 필요.
-
프로젝트 생성이 완료되면 Project URL과 API Key(anon/public key, service key)를 자동으로 제공.
- Settings → API 메뉴에서 확인 가능.
3. .env.local
파일에 Supabase 키 저장
Next.js에서는 환경변수 파일 .env.local
을 사용해 Supabase URL과 API Key를 안전하게 관리한다.
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
NEXT_PUBLIC_
prefix는 Next.js에서 클라이언트와 서버 모두에서 접근 가능한 환경변수임을 의미.service key
는 절대 클라이언트에서 사용하지 않고, 서버 액션, Route Handler 같은 서버 사이드 코드에서만 사용
요약
- Supabase 프로젝트 생성 → 자동으로 관리형 Postgres, Auth, Storage, Realtime, API가 준비됨.
- 환경변수로 API 호출에 필요한 URL과 Key를 안전하게 관리.
- 이후 Next.js 코드에서 Supabase 클라이언트를 초기화하여 사용.
Next.js와 Supabase 연동 설정
How to setup Supabase with Nextjs for authentication | Supabase Auth
Supabase 클라이언트 설치
npm install @supabase/supabase-js @supabase/ssr
@supabase/ssr
는 Next.js의 App Router 지원을 위한 어댑터 함수 라이브러리이다.
Supabase Type 연동
Supabase는 타입스크립트에서 사용할 수 있도록 CLI를 통한 타입 생성을 지원한다.
npx supabase gen types typescript --project-id "$PROJECT_REF" --schema public > types/supabase.ts
위의 명령어를 자주 사용하므로 package.json의 script로 지정해두면 좋다.
{
"name": "next-js-boilerplate",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"supabase:gen": "npx supabase gen types typescript --project-id {$PROJECT_REF} --schema public > types/supabase.ts",
"test": "vitest"
},
Supabase createClient 작성
브라우저에서 실행될 Supabase client와 서버에서 실행될 Supabase client, 두 개를 나눠서 작성하게 된다.
Client용 createClient
utils/supabase/client.ts
import { Database } from "@/types/supabase";
import { createBrowserClient } from "@supabase/ssr";
export const createClient = () =>
createBrowserClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
createBrowserClient
는 window
환경과 브라우저의 쿠키를 기반으로 작동하는 클라이언트를 반환한다.
Server용 createClient
utils/supabase/server.ts
"use server";
import { Database } from "@/types/supabase";
import { createServerClient } from "@supabase/ssr";
import { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";
import { cookies } from "next/headers";
export const createClient = async (
initialCookieStore?: ReadonlyRequestCookies
) => {
const cookieStore = initialCookieStore || (await cookies());
return createServerClient<Database>(
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);
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
// The `set` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
}
);
};
createServerClient
는 Request의 Cookies를 기반으로 세션을 갱신한다.
위의 코드에서는 로그인/로그아웃에 대응하기 위해 setAll(cookiesToSet)
부분도 작성되어 있다.
Middleware 등록
Setting up Server-Side Auth for Next.js
앞서 설명한 setAll(cookiesToSet)
부분을 미들웨어에서 처리하도록 작성할 수 있다.
utils/supabase/middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function updateSession(request: NextRequest) {
let supabaseResponse = NextResponse.next({
request,
})
// 요청으로 받은 cookies로 세션을 업데이트하는 부분
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, options }) => request.cookies.set(name, value))
supabaseResponse = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
)
},
},
}
)
// supabase.auth로부터 유저 정보를 받아 특정 경로에서 리다이렉트 하는 예시
const {
data: { user },
} = await supabase.auth.getUser()
if (
!user &&
!request.nextUrl.pathname.startsWith('/login') &&
!request.nextUrl.pathname.startsWith('/auth')
) {
const url = request.nextUrl.clone()
url.pathname = '/login'
return NextResponse.redirect(url)
}
return supabaseResponse
}
위의 예시에서는 요청으로 받은 cookies로부터 supabase client를 업데이트 하는 부분과 supabase client의 유저 정보를 바탕으로 리다이렉트를 하는 부분으로 나뉘어 있다.
해당 미들웨어 함수를 실제 미들웨어에 등록하면 된다.
middleware.ts
import { type NextRequest } from "next/server";
import { updateSession } from "@/utils/supabase/middleware";
export async function middleware(request: NextRequest) {
return await updateSession(request);
}
export const config = {
matcher: [
/*
* 모든 경로에 대해 미들웨어가 적용되도록 하는 matcher
*/
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
};
supabase 클라이언트를 위한 updateSession을 미들웨어에 등록하고,
config에는 모든 경로에 대해 미들웨어가 실행되도록 한다.