Supabase는 PostgreSQL을 백엔드로 사용하면서도 REST API와 Realtime 구독을 기본 제공한다. supabase-js는 이 모든 기능을 브라우저와 Node.js 환경에서 동일한 인터페이스로 사용할 수 있게 해주는 공식 JavaScript SDK다. 별도의 ORM 없이 타입 안전한 쿼리 빌더를 체이닝 방식으로 구성할 수 있어 개발 속도가 빠르다.
프로젝트 URL과 anon 키만 있으면 클라이언트를 생성할 수 있다.
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
anon key — Row Level Security(RLS)가 적용된 상태에서 인증되지 않은 사용자에게 허용되는 공개 키. 클라이언트 번들에 포함되어도 안전하다.
// 전체 컬럼 조회
const { data, error } = await supabase
.from('posts')
.select('*')
// 특정 컬럼 + 필터 체이닝
const { data } = await supabase
.from('posts')
.select('id, title, created_at')
.eq('category', 'database')
.order('created_at', { ascending: false })
.limit(10)
필터 체이닝은 메서드를 순서대로 연결하는 방식으로, 내부적으로 PostgREST 쿼리 파라미터로 변환된다. eq, neq, gt, lt, like, in 등 PostgreSQL 연산자 대부분을 지원한다.
// insert
const { data, error } = await supabase
.from('posts')
.insert({ title: '새 글', category: 'database' })
.select()
// update
await supabase
.from('posts')
.update({ title: '수정된 글' })
.eq('id', 42)
// delete
await supabase
.from('posts')
.delete()
.eq('id', 42)
insert 뒤에 .select를 체이닝하면 삽입된 행을 즉시 반환받을 수 있다. update와 delete는 반드시 필터 조건을 붙여야 한다. 조건 없이 호출하면 테이블 전체에 적용된다.
const { data } = await supabase
.rpc('get_popular_posts', { min_views: 100 })
rpc — Remote Procedure Call. Supabase에서는 PostgreSQL 저장 함수(stored function)를 HTTP 엔드포인트로 노출하며, rpc로 호출한다.
복잡한 집계나 트랜잭션 로직은 PostgreSQL 함수로 작성하고 rpc로 호출하는 패턴이 권장된다.
// 이메일 로그인
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'secret',
})
// 파일 업로드
const { data } = await supabase.storage
.from('avatars')
.upload('public/avatar.png', file, { upsert: true })
supabase.auth와 supabase.storage는 동일한 클라이언트 인스턴스에서 접근한다. 로그인 후 세션은 자동으로 관리되며, 이후 .from 쿼리에 JWT가 자동 첨부된다.
Browser / Node.js
|
createClient()
|
┌───┴──────────────────────────┐
│ supabase-js SDK │
│ .from().select() → REST │
│ .auth.* → GoTrue │
│ .storage.* → S3-like │
│ .rpc() → REST │
└───────────────────┬──────────┘
|
Supabase Cloud
(PostgreSQL + PostgREST)
하나의 supabase 인스턴스가 DB 쿼리, 인증, 파일 스토리지를 모두 처리한다. 각 요청은 내부적으로 HTTP 또는 WebSocket으로 변환되어 Supabase 백엔드로 전달된다.
모든 메서드는 { data, error } 구조를 반환한다. error가 null이 아니면 실패다.
const { data, error } = await supabase.from('posts').select('*')
if (error) {
console.error(error.message)
throw error
}
// data는 여기서 null이 아님이 보장됨
예외를 throw하는 대신 결과 객체를 반환하는 방식이므로, try/catch 없이도 명시적인 에러 분기가 가능하다.