Supabase는 무엇인가: Postgres 위에 얹은 백엔드 한 벌
TL;DR
- Supabase는 PostgreSQL을 중심으로 인증, 파일 저장, API, 서버 함수를 한 번에 주는 BaaS다.
- 브라우저가 DB를 직접 부르는 구조라서, 보안은 키가 아니라 DB 권한(RLS)이 맡는다.
- 무료 플랜으로 작은 서비스를 충분히 운영할 수 있다. 대신 용량과 일시 정지 조건을 알고 써야 한다.
들어가며
개인 프로젝트를 만들 때 가장 시간이 많이 드는 건 화면보다 백엔드의 기본기다. DB 서버 띄우기, 로그인 만들기, 파일 업로드 저장소, API 서버, 배포. Supabase는 이것들을 한 벌로 준다. 프론트엔드만 만들어 배포해도 서비스가 돌아간다.
1. Supabase가 주는 것
| 기능 | 내용 |
|---|---|
| Database | 진짜 PostgreSQL. SQL, 뷰, 함수, 트리거, 확장 모두 쓸 수 있다 |
| 자동 API | 표를 만들면 REST API가 바로 생긴다(PostgREST). 함수는 RPC로 부른다 |
| Auth | 이메일, 소셜 로그인, 매직 링크. 로그인한 사용자는 DB 권한 규칙에서 바로 쓸 수 있다 |
| Storage | 이미지 같은 파일 저장. 버킷별 권한 규칙 |
| Edge Functions | 짧은 서버 코드(Deno/TypeScript). 외부 API 호출, 웹훅 받기 등 |
| Cron | pg_cron으로 DB 안에서 예약 작업 |
Firebase와 무엇이 다른가
둘 다 BaaS지만 바탕이 다르다.
| Supabase | Firebase | |
|---|---|---|
| DB | 관계형(PostgreSQL) | 문서형(Firestore) |
| 쿼리 | SQL, 조인, 집계 | 컬렉션 단위, 조인 없음 |
| 옮겨 가기 | 표준 Postgres라 덤프해서 다른 곳으로 옮기기 쉽다 | Firebase 전용 구조 |
| 직접 운영 | 오픈 소스라 직접 띄울 수도 있다 | 불가 |
데이터 사이 관계가 많거나 SQL로 통계를 내야 하면 Supabase가 편하다.
2. 키 두 개: 공개 키와 비밀 키
Supabase 프로젝트를 만들면 키를 두 종류 준다.
| 키 | 어디에 두나 | 권한 |
|---|---|---|
| 공개 키 (anon / publishable) | 브라우저 코드에 들어간다. 누구나 볼 수 있다 | RLS 규칙을 따른다 |
| 비밀 키 (service_role / secret) | 서버 환경변수에만 | RLS를 건너뛴다. 모든 데이터에 접근 |
처음 쓰는 사람이 가장 많이 헷갈리는 부분이 여기다. 공개 키는 숨기는 키가 아니다. 브라우저가 DB를 직접 부르려면 키가 브라우저에 있어야 하니, 숨길 방법이 없다. 그래서 "공개 키로 무엇을 할 수 있나"는 키가 아니라 DB 권한 규칙이 정한다.
비밀 키는 반대로 절대 브라우저에 가면 안 된다. 서버 코드에서만 쓰고, 쓸 때는 RLS가 걸러 주던 조건(공개된 글만 등)을 직접 쿼리에 걸어야 한다.
3. RLS: 행 수준 보안
RLS(Row Level Security)는 Postgres 기능으로, 표의 각 행마다 누가 읽고 쓸 수 있는지를 규칙으로 정한다.
alter table posts enable row level security;
-- 누구나 공개된 글만 읽는다
create policy "public read" on posts for select
using (status = 'published' and published_at <= now());
-- 작성자 본인만 고친다
create policy "owner update" on posts for update
using (auth.uid() = author_id);- RLS를 켜고 규칙이 하나도 없으면 아무것도 못 읽는다. 기본이 닫힘이다.
auth.uid()로 로그인한 사용자를 규칙 안에서 바로 쓴다.- 칸 단위 권한도 같이 쓸 수 있다.
grant select (id, title) on posts to anon처럼 하면 공개 키로는 그 칸만 읽힌다. 행은 열어도 본문 같은 칸은 숨길 수 있다.
RLS를 제대로 짜면 API 서버 없이도 안전하게 브라우저에서 DB를 부를 수 있다. 반대로 RLS를 잊으면, 공개 키를 가진 누구나 표 전체를 읽을 수 있다. Supabase 대시보드도 RLS가 꺼진 표를 경고해 준다.
4. RPC 함수: 규칙이 복잡할 때
"좋아요는 한 사람이 하루 한 번만", "문의는 10분에 몇 건까지"처럼 규칙이 복잡하면, 표를 직접 열기보다 DB 함수를 만들어 그것만 부르게 한다.
create function add_like(p_post_id bigint) returns void
language plpgsql security definer set search_path = public as $$
begin
-- 검사 → 기록 → 숫자 올리기를 한 트랜잭션에서
...
end $$;
revoke all on function add_like(bigint) from public;
grant execute on function add_like(bigint) to anon;브라우저는 supabase.rpc("add_like", { p_post_id: 1 })로 부른다. security definer 함수는 만든 사람의 권한으로 돌기 때문에, 표는 닫아 두고 함수만 열어 두는 설계가 가능하다. 이때 search_path를 고정하고, 함수 안에서 입력을 꼼꼼히 검사해야 한다.
5. 예약 작업과 Edge Function
- pg_cron: "매일 새벽 오래된 기록 지우기" 같은 일을 DB 안에서 예약한다. 별도 서버가 필요 없다.
- Edge Functions: 외부 API를 부르거나, 다른 서비스의 웹훅을 받거나, 비밀 키가 필요한 일을 처리하는 짧은 서버 코드다. 예를 들어 "외부 프로젝트가 API 키로 문서를 밀어 넣는 입구"를 Edge Function으로 만들 수 있다.
6. 무료 플랜으로 쓸 때 알아 둘 점
- DB 용량에 한도가 있다. 조회 기록처럼 매일 쌓이는 데이터는 보관 기간을 정하고 예약 작업으로 지운다.
- 오래 안 쓰면 일시 정지된다. 일정 기간 요청이 없으면 프로젝트가 멈춘다. 꾸준히 쓰는 서비스라면 문제없다.
- 백업은 직접 챙긴다. 무료 플랜은 자동 백업 보관이 짧다. 주기적으로 데이터를 내려받아 두는 작업을 따로 만들어 두면 안심이 된다.
- 마이그레이션은 파일로 남긴다. 대시보드에서 바로 고치기보다 SQL 파일로 쌓아 두면, 무엇이 언제 바뀌었는지 남고 다른 환경에 똑같이 적용할 수 있다.
정리
Supabase는 "백엔드를 안 만들어도 되는 도구"라기보다, 백엔드의 많은 부분을 DB 안으로 옮겨 주는 도구에 가깝다. 그래서 SQL과 권한 설계에 익숙할수록 더 잘 쓸 수 있다. 개인 프로젝트들에서 Supabase를 어디에 쓰고 어디에 안 썼는지는 개인 프로젝트 인프라 설계에 정리했다.