김솔비 블로그
기술 블로그

Supabase는 무엇인가: Postgres 위에 얹은 백엔드 한 벌

5분 읽기

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 호출, 웹훅 받기 등
Cronpg_cron으로 DB 안에서 예약 작업

Firebase와 무엇이 다른가

둘 다 BaaS지만 바탕이 다르다.

SupabaseFirebase
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 기능으로, 표의 각 행마다 누가 읽고 쓸 수 있는지를 규칙으로 정한다.

sql
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 함수를 만들어 그것만 부르게 한다.

sql
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를 어디에 쓰고 어디에 안 썼는지는 개인 프로젝트 인프라 설계에 정리했다.