개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Supabase PostgreSQL — 관계형 데이터베이스 기반

2025년 3월 30일
SupabasePostgreSQLSQLDatabaseTransaction

Supabase는 Firebase의 대안으로 소개되지만, 내부는 PostgreSQL이라는 강력한 관계형 데이터베이스 위에 세워져 있다. NoSQL이 아닌 SQL을 중심으로 설계되어 있기 때문에, 복잡한 관계형 데이터 모델도 자연스럽게 표현할 수 있다. 단순한 BaaS를 넘어 PostgreSQL의 모든 기능을 그대로 활용할 수 있다는 점이 핵심이다.

PostgreSQL 특징

PostgreSQL은 오픈소스 관계형 데이터베이스 중 가장 기능이 풍부한 시스템이다. ACID 속성을 완전히 지원하며, JSON 타입, 배열 타입, 사용자 정의 타입 등 다양한 데이터 타입을 제공한다.

[Client]
   |
   v
[Supabase API Layer]  ← REST / GraphQL / Realtime
   |
   v
[PostgreSQL Engine]
   |-- Tables (스키마 기반 관계형 데이터)
   |-- Views (읽기 전용 가상 테이블)
   |-- Functions (서버 사이드 로직)
   |-- Indexes (쿼리 성능 최적화)
   |-- Row Level Security (행 단위 접근 제어)

ACID: Atomicity(원자성), Consistency(일관성), Isolation(격리성), Durability(지속성) — 트랜잭션의 신뢰성을 보장하는 네 가지 속성

SQL 지원과 Dashboard 쿼리

Supabase Dashboard의 SQL Editor에서 PostgreSQL 쿼리를 직접 실행할 수 있다. 테이블 생성부터 복잡한 JOIN 쿼리까지 브라우저에서 바로 실행하고 결과를 확인할 수 있다.

-- 테이블 생성
CREATE TABLE posts (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  title TEXT NOT NULL,
  content TEXT,
  user_id UUID REFERENCES auth.users(id),
  created_at TIMESTAMPTZ DEFAULT now()
);

-- JOIN 쿼리
SELECT p.title, u.email
FROM posts p
JOIN auth.users u ON p.user_id = u.id
WHERE p.created_at > now() - interval '7 days';

Transaction

여러 쿼리를 하나의 단위로 묶어 원자적으로 실행해야 할 때 Transaction을 사용한다. 중간에 오류가 발생하면 전체가 롤백된다.

BEGIN;
  INSERT INTO orders (user_id, total) VALUES ($1, $2);
  UPDATE inventory SET stock = stock - 1 WHERE product_id = $3;
COMMIT;

Rollback: 트랜잭션 중 오류 발생 시 모든 변경을 이전 상태로 되돌리는 연산

Index

Index는 특정 컬럼에 대한 검색 속도를 높이기 위한 자료구조다. 조회가 빈번한 컬럼에 인덱스를 추가하면 풀 테이블 스캔을 피할 수 있다.

-- 단일 컬럼 인덱스
CREATE INDEX idx_posts_user_id ON posts(user_id);

-- 복합 인덱스
CREATE INDEX idx_posts_user_date ON posts(user_id, created_at DESC);
인덱스 유형용도
B-Tree일반 등호/범위 조건 (기본값)
GIN배열, JSONB, 전문 검색
GiST지리 데이터, 범위 타입

View와 Function

View는 복잡한 쿼리를 저장해두고 테이블처럼 조회하는 가상 테이블이다. Function은 PostgreSQL 서버 내에서 실행되는 로직으로, 네트워크 왕복 없이 복잡한 연산을 처리한다.

-- View 생성
CREATE VIEW recent_posts AS
SELECT * FROM posts
WHERE created_at > now() - interval '30 days';

-- Function 생성
CREATE OR REPLACE FUNCTION get_post_count(uid UUID)
RETURNS INTEGER AS $$
  SELECT COUNT(*) FROM posts WHERE user_id = uid;
$$ LANGUAGE sql STABLE;

STABLE: 같은 트랜잭션 내에서 동일한 인자에 동일한 결과를 반환한다는 힌트 — PostgreSQL 쿼리 최적화에 활용됨

Supabase는 PostgreSQL 위에 얇은 API 레이어를 올린 구조이므로, PostgreSQL을 직접 다루는 능력이 곧 Supabase를 잘 쓰는 능력이 된다.

← 이전 글Supabase란? — PostgreSQL 기반 오픈소스 BaaS
다음 글 →Supabase Table — 데이터를 저장하는 기본 구조