RSS듀오랩스
데이터베이스

Supabase와 직접 구성한 PostgreSQL: 사내 업무 시스템 선택 기준

작성자
듀오랩스 대표·8분 읽기

사내 업무 시스템을 만들 때 데이터베이스를 고르는 질문은 대개 이렇게 나옵니다. 「그냥 PostgreSQL 쓰면 되지 않나요? Supabase 는 뭐가 다른가요?」

맞는 질문입니다. Supabase 의 데이터베이스는 PostgreSQL 이고, 특별한 방언이나 독자 엔진이 아닙니다. 그래서 「DB 를 고르는 문제」로 보면 둘은 같습니다. 실제로 갈리는 것은 그 옆에 딸려 오는 것들입니다.

PostgreSQL 대 Supabase 로 비교하는 시각

이 비교를 「PostgreSQL vs Supabase」로 두면 답이 나오지 않습니다. 둘 다 PostgreSQL 이기 때문입니다.

비교할 대상은 이렇게 놓아야 합니다.

A: 관리형 PostgreSQL + 인증 서비스 + 파일 저장소 + 백업 + 모니터링 + 커넥션 풀러
B: Supabase (위 항목이 한 프로젝트 안에 묶여 있음)

A 를 고르면 각 칸을 직접 고르고 잇습니다. 자유도가 높은 대신, 그 연결을 만들고 유지하는 일이 남습니다. 1인 개발사라면 이 「연결을 유지하는 일」의 비용이 생각보다 큽니다.

가장 크게 갈리는 지점: 인증과 행 수준 보안의 연결

기능 목록을 나열하는 것보다, 실제로 차이가 드러나는 한 곳을 보는 편이 빠릅니다.

멀티테넌트 업무 시스템에서 가장 위험한 실수는 조회 조건 하나를 빠뜨리는 것입니다.

-- 의도
select * from orders where tenant_id = $1 and id = $2;

-- 실수
select * from orders where id = $1;

앱 코드에만 의존하면 이 한 줄이 곧 다른 회사 데이터 노출입니다. 그래서 PostgreSQL 의 행 수준 보안(RLS)을 켜서 데이터베이스가 한 번 더 거르게 합니다. 여기까지는 어떤 PostgreSQL 이든 같습니다.

차이는 「지금 요청한 사용자가 누구인지」를 데이터베이스가 어떻게 아느냐입니다. Supabase 의 RLS 문서는 자기네 Auth 를 쓰면 auth.uid() 로 요청한 사용자의 id 를 바로 쓸 수 있다고 안내합니다.

create policy "본인 프로필만 조회"
on profiles for select
to authenticated
using ((select auth.uid()) = user_id);

직접 구성하는 쪽에서는 이 연결을 스스로 만들어야 합니다. 세션에서 사용자 id 를 꺼내 요청마다 데이터베이스 세션 변수로 넘기고, 정책이 그 값을 읽게 하는 구조입니다. 만들 수 있고, 만들면 동작합니다. 다만 트랜잭션마다 그 값을 세팅하는 코드가 빠지면 정책이 조용히 무력해진다는 점이 위험합니다.

정리하면 RLS 는 어디서나 쓸 수 있지만, Supabase 는 「로그인 → 토큰 → 정책」의 배선을 기본으로 깔아 둡니다. 직접 구성하면 그 배선이 우리 코드의 일부가 됩니다.

딸려 오는 것들의 목록

인증 말고도 프로젝트 하나에 함께 오는 것들이 있습니다. 문서에서 확인되는 범위만 적으면 이렇습니다.

항목 Supabase 에서
MFA Auth 기능으로 제공. 인증 앱(TOTP)과 전화 방식 문서가 따로 있다
파일 저장소 Storage 는 기본적으로 정책 없이는 업로드를 허용하지 않고, storage.objects 테이블의 RLS 정책으로 접근을 연다
백업 Pro 플랜은 최근 7일, Team 14일, Enterprise 30일치 일일 백업. 더 촘촘하면 PITR 을 켠다. 무료 플랜은 CLI 로 직접 내보내라고 안내한다
커넥션 서버리스·엣지 함수에는 공유 풀러의 transaction 모드를 권한다. 짧은 연결이 많이 열리기 때문이다

마지막 줄이 Vercel 같은 서버리스 환경에서 특히 중요합니다. 함수 인스턴스가 여러 개 뜨면 연결이 그만큼 열립니다. 직접 구성하는 쪽이라면 풀러를 따로 두거나 서버리스용 드라이버를 골라야 합니다. 어느 쪽이든 「연결 방식」은 반드시 결정해야 하는 항목이고, 미루면 운영에서 드러납니다.

그래서 언제 Supabase 를 고르나

제가 보기에 기준은 팀 규모와 보안 책임의 총량입니다.

Supabase 쪽이 맞는 경우

  • 1인이나 소수가 만들고 운영한다
  • 인증, 권한, 파일 접근 통제를 처음부터 다 만들 시간이 없다
  • 멀티테넌트라 데이터 격리를 코드 밖에서도 한 번 더 걸러야 한다
  • 서버리스 배포(Vercel 등)라 커넥션 관리가 필요하다

직접 구성이 맞는 경우

  • 이미 쓰는 인증 체계(사내 SSO, 기존 회원 DB)가 있어 Auth 를 따로 두면 오히려 이중이 된다
  • 데이터베이스가 특정 리전·망 안에 있어야 하는 요구가 있다
  • PostgreSQL 설정을 깊게 손봐야 하거나, 관리형에서 막히는 확장을 써야 한다
  • 이미 운영 인력과 백업·모니터링 체계가 있다

성능 때문에 고르는 문제는 아니라고 봅니다. 같은 PostgreSQL 이고, 사내 업무 시스템 규모의 부하는 어느 쪽에서도 문제가 되지 않습니다. 고르는 이유는 혼자 운영하면서 빠뜨릴 수 있는 항목의 수를 줄이는 것입니다.

종속의 정도

「Supabase 에 묶이는 것 아닌가」라는 걱정은 층을 나눠 보면 정도가 달라집니다.

옮기기
데이터 (PostgreSQL) 표준 PostgreSQL 이라 덤프와 복원으로 옮길 수 있다
RLS 정책 SQL 이므로 함께 옮겨간다. 다만 auth.uid() 같은 헬퍼는 대체가 필요하다
Auth (사용자 계정·해시) 옮길 수 있지만 세션·소셜 로그인 설정은 다시 만든다
Storage 파일은 옮기고, 접근 정책은 새 저장소의 방식으로 다시 쓴다
Realtime·Edge Function 등 쓰고 있었다면 대체 구성을 새로 만든다

핵심이 PostgreSQL 이라는 점이 여기서 값을 합니다. 데이터 자체는 표준 도구로 나갈 수 있습니다. 대신 플랫폼 기능을 깊게 쓸수록 이전 비용이 커집니다. 이전 가능성을 중요하게 본다면 RLS 정책에서 플랫폼 헬퍼 함수 사용을 한 군데로 모아 두는 정도의 준비는 해 둘 만합니다.

고르기 전에 답해 둘 것

질문 확인
인증을 직접 만들 것인가 만들면 MFA·세션·재설정까지 포함해서 본다
멀티테넌트인가 그렇다면 RLS 를 어느 쪽이든 켠다
배포가 서버리스인가 커넥션 방식(풀러·전용 드라이버)을 먼저 정한다
백업 보관 기간은 얼마나 필요한가 플랜별 보관 일수와 PITR 필요 여부를 확인한다
파일 접근 통제가 필요한가 저장소의 권한 모델을 먼저 본다

이 다섯 개를 답하고 나면 Supabase 든 직접 구성이든 결정이 거의 정해진다고 봅니다. 답을 미룬 채 「일단 PostgreSQL 하나 띄우고 시작」하면, 나중에 다섯 개를 운영 중에 하나씩 만나게 됩니다.

여기까지가 확실한 부분

auth.uid() 로 RLS 정책을 쓰는 방식, Storage 가 정책 없이는 업로드를 허용하지 않는다는 점, 플랜별 일일 백업 보관 기간과 PITR 안내, 서버리스 환경에 transaction 모드 공유 풀러를 권한다는 점, MFA 기능의 존재는 Supabase 문서 기준입니다. 직접 구성할 때 세션 변수로 사용자 id 를 넘기는 방식은 PostgreSQL 에서 흔히 쓰는 패턴이고, 구체적인 구현은 쓰는 드라이버와 ORM 에 따라 다릅니다. 요금과 플랜별 한도는 바뀌므로 결정 시점에 각 서비스의 가격 페이지를 다시 확인해야 합니다.

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.