Supabase 자주 하는 실수 10가지

카페인코더·2026년 6월 19일

AI 웹앱 보안 점검

목록 보기
6/11
post-thumbnail

Supabase는 데이터베이스, 인증, 파일 저장소, API를 한곳에서 사용할 수 있어 빠르게 웹앱을 만들 때 유용합니다.

특히 AI 개발 도구와 함께 사용하면 백엔드를 처음 다루는 사람도 회원가입, 문의폼, 예약 기능을 비교적 빠르게 구현할 수 있습니다.

하지만 기능이 동작하는 것과 안전하게 운영할 수 있는 것은 다른 문제입니다.

Supabase 자체가 위험한 것은 아닙니다. 대부분의 문제는 API 키, 권한, Storage, 인증 설정을 정확히 이해하지 못한 상태에서 배포할 때 발생합니다.

이번 글에서는 Supabase로 웹앱을 만들 때 자주 하는 실수 10가지를 정리해보겠습니다.


1. 공개용 API 키가 보인다는 이유만으로 유출이라고 생각한다

Supabase 프로젝트를 프론트엔드에 연결하면 API 키가 브라우저 코드나 네트워크 요청에서 보일 수 있습니다.

처음 발견하면 키가 유출됐다고 생각하기 쉽지만, Supabase의 publishable key는 웹과 모바일 앱에서 공개되는 것을 전제로 만들어진 키입니다. 기존 프로젝트의 anon key도 같은 용도로 사용됩니다.

중요한 것은 키가 보이느냐가 아니라 그 키로 어떤 데이터에 접근할 수 있느냐입니다.

이렇게 확인해보세요

  • 프론트엔드에는 publishable key 또는 기존 anon key만 사용했는가
  • 비로그인 사용자가 조회하거나 수정할 수 있는 데이터는 무엇인가
  • anon, authenticated 역할에 필요한 권한만 허용했는가
  • RLS 정책이 실제 사용자 권한에 맞게 설정되어 있는가

공개용 키는 숨기는 것보다 권한을 제한하는 것이 핵심입니다.

Supabase API 키 공식 문서


2. 비밀 키를 프론트엔드 환경변수에 넣는다

secret key와 기존 service_role key는 공개용 키와 다릅니다.

이 키들은 높은 권한을 가지며 RLS를 우회할 수 있으므로, 브라우저나 모바일 앱에 포함되면 안 됩니다.

환경변수에 넣었다고 모두 비밀이 되는 것도 아닙니다. 프론트엔드 빌드에 포함되는 공개 환경변수는 최종 JavaScript 파일에서 확인될 수 있습니다.

프론트엔드에 있으면 안 되는 값

  • sb_secret_... 형식의 Secret key
  • 기존 service_role key
  • 데이터베이스 비밀번호
  • JWT Secret
  • 외부 서비스의 관리자용 API 키

이 값들은 서버, Edge Function 또는 접근이 통제된 백엔드에서만 사용해야 합니다.

이렇게 확인해보세요

프로젝트 전체에서 다음 문자열을 검색합니다.

service_role
sb_secret_
DATABASE_URL
DB_PASSWORD
JWT_SECRET

Git 저장소에 커밋된 적이 있다면 코드에서 지우는 것만으로 끝나지 않습니다. 해당 키를 교체하고 커밋 기록과 배포 환경도 함께 확인해야 합니다.


3. 로그인 기능을 만들면 데이터 권한도 해결됐다고 생각한다

로그인과 권한은 서로 다른 문제입니다.

  • 인증(Authentication): 이 사용자가 누구인지 확인
  • 인가(Authorization): 이 사용자가 어떤 데이터에 접근할 수 있는지 결정

Supabase Auth로 로그인에 성공했다고 해서 사용자가 자신의 데이터만 볼 수 있도록 자동 설정되는 것은 아닙니다.

예를 들어 예약 목록을 조회하는 기능에서 사용자 조건이 빠지면, 로그인한 사용자가 다른 사용자의 예약까지 조회할 수 있습니다.

이렇게 확인해보세요

  1. A 계정으로 데이터를 생성한다.
  2. B 계정으로 로그인한다.
  3. B 계정이 A의 데이터를 조회할 수 있는지 확인한다.
  4. 조회뿐 아니라 수정과 삭제도 각각 확인한다.

로그인 성공 여부보다 다른 사용자의 데이터에 접근할 수 없는지를 확인해야 합니다.

Supabase Auth 공식 문서


4. RLS를 켜기만 하면 안전하다고 생각한다

RLS(Row Level Security)는 사용자마다 접근할 수 있는 행을 제한하는 PostgreSQL 기능입니다.

Supabase의 public 스키마처럼 API에 노출된 테이블은 RLS 설정이 중요합니다.

Dashboard의 Table Editor로 만든 테이블은 RLS가 기본 활성화될 수 있지만, SQL Editor나 직접 작성한 SQL로 만든 테이블은 별도로 활성화해야 할 수 있습니다.

RLS를 켰더라도 정책을 지나치게 넓게 작성하면 데이터가 그대로 노출될 수 있습니다.

using (true)

이 조건은 적용 대상 역할과 작업에 따라 모든 행을 허용할 수 있습니다.

테이블마다 확인할 항목

  • RLS가 활성화되어 있는가
  • SELECT, INSERT, UPDATE, DELETE 정책을 구분했는가
  • 정책 대상이 anon인지 authenticated인지 명확한가
  • 사용자의 id와 데이터의 소유자 컬럼을 비교하는가
  • 비로그인, 사용자 A, 사용자 B 상태에서 각각 테스트했는가

권한 판단에 사용자가 직접 수정할 수 있는 user_metadata를 사용하는 것도 주의해야 합니다. 역할과 같은 중요한 권한 정보는 사용자가 임의로 바꿀 수 없는 데이터를 기준으로 판단해야 합니다.

Supabase RLS 공식 문서


5. Storage 버킷을 공개로 만들고 파일명만 숨긴다

Supabase Storage에는 Public 버킷과 Private 버킷이 있습니다.

Public 버킷의 파일은 URL을 알고 있다면 누구나 조회할 수 있습니다. 파일명을 복잡하게 만들었다고 접근 권한이 생기는 것은 아닙니다.

Public으로 사용할 수 있는 예

  • 공개 프로필 이미지
  • 블로그 대표 이미지
  • 누구나 볼 수 있는 서비스 이미지

Private으로 관리해야 하는 예

  • 계약서
  • 상담 첨부파일
  • 신분증이나 증빙자료
  • 사용자 개인 문서
  • 외부에 공개하면 안 되는 이미지

Private 버킷은 RLS 정책과 인증 정보를 이용해 접근을 통제할 수 있으며, 일정 시간만 유효한 Signed URL을 사용할 수도 있습니다.

이렇게 확인해보세요

  • 로그아웃 상태에서 파일 URL이 열리는가
  • 다른 사용자 계정으로 같은 파일을 조회할 수 있는가
  • 업로드뿐 아니라 조회, 수정, 삭제 정책도 설정했는가
  • 파일 크기와 허용할 파일 형식을 제한했는가

Supabase Storage 버킷 공식 문서


6. 화면의 입력값 검사만 믿는다

회원가입이나 문의폼에서 글자 수와 이메일 형식을 검사했다고 해도 브라우저의 검증만으로는 충분하지 않습니다.

사용자는 화면을 거치지 않고 Supabase API에 직접 요청할 수 있기 때문입니다.

함께 적용할 수 있는 방법

  • 데이터베이스의 NOT NULL, UNIQUE, CHECK 제약조건
  • RLS의 WITH CHECK 정책
  • 서버 또는 Edge Function에서의 입력값 검증
  • 허용할 길이, 형식, 값의 범위 제한
  • 중복 요청과 과도한 요청 제한

예를 들어 예약 인원을 화면에서 1명 이상으로 제한했다면 데이터베이스에도 같은 제약조건을 둘 수 있습니다.

check (guest_count >= 1)

화면 검증은 사용자의 실수를 줄이고, 서버와 데이터베이스 검증은 잘못된 요청이 저장되는 것을 막습니다.


7. 인증 리디렉션과 요청 제한을 기본값으로 둔다

이메일 인증, 비밀번호 재설정, 소셜 로그인을 사용하면 인증 후 사용자를 돌려보낼 URL을 설정하게 됩니다.

개발 중 사용한 localhost 주소나 임시 배포 주소가 운영 설정에 남아 있으면 인증 링크가 잘못된 화면으로 연결될 수 있습니다.

확인할 항목

  • 운영 환경의 Site URL이 정확한가
  • 허용된 Redirect URL만 등록되어 있는가
  • 사용하지 않는 개발·미리보기 주소가 남아 있지 않은가
  • 비밀번호 재설정 링크가 올바른 화면으로 이동하는가
  • 이메일과 OTP 요청 제한이 서비스 상황에 맞는가

Supabase Auth에는 인증 API에 대한 기본 Rate Limit이 있지만, 이것만으로 서비스의 모든 API와 폼이 보호되는 것은 아닙니다.

문의 등록이나 예약 생성처럼 직접 만든 기능은 별도의 요청 제한이 필요할 수 있습니다.

Redirect URL 공식 문서

Auth Rate Limit 공식 문서


8. 운영 DB를 Dashboard에서 직접 수정하고 기록을 남기지 않는다

초기 개발에서는 Dashboard에서 테이블과 컬럼을 직접 수정하는 것이 편리합니다.

하지만 서비스가 운영되기 시작하면 누가 어떤 구조를 변경했는지 추적하기 어려워집니다. 개발 환경과 운영 환경의 구조가 달라지는 문제도 생길 수 있습니다.

Supabase는 데이터베이스 변경사항을 Migration 파일로 관리할 수 있습니다.

supabase/migrations/

Migration으로 관리하면 좋은 항목

  • 테이블과 컬럼 생성
  • 인덱스와 제약조건
  • RLS 활성화
  • 접근 정책
  • 데이터베이스 함수와 트리거

Dashboard에서 작업하더라도 변경 내용을 Migration으로 남겨 Git에서 관리하면 동일한 환경을 다시 만들고 변경 이력을 검토하기 쉬워집니다.

Supabase Migration 공식 문서


9. 자동 백업이 모든 데이터를 복구해준다고 생각한다

백업은 요금제와 설정에 따라 제공 범위와 보관 기간이 다릅니다. 따라서 프로젝트의 현재 백업 정책을 직접 확인해야 합니다.

특히 주의할 점은 데이터베이스 백업에 Storage의 실제 파일이 포함되지 않는다는 것입니다.

데이터베이스에는 Storage 객체의 메타데이터가 저장되지만, 삭제된 파일 자체가 데이터베이스 복원으로 되살아나는 것은 아닙니다.

이렇게 확인해보세요

  • 현재 요금제에서 제공되는 백업 범위와 보관 기간
  • 마지막 백업이 정상적으로 생성된 시점
  • 복원 시 손실될 수 있는 데이터의 범위
  • Storage 파일의 별도 백업 필요 여부
  • 실제 복원 절차와 예상 중단 시간
  • 중요한 데이터의 외부 백업 여부

무료 프로젝트라면 필요한 데이터를 정기적으로 내보내는 방법도 검토해야 합니다.

백업이 존재하는 것과 필요한 데이터를 실제로 복구할 수 있는 것은 다릅니다.

Supabase Database Backups 공식 문서


10. 기능이 동작하면 운영 준비도 끝났다고 생각한다

개발 환경에서 회원가입과 데이터 저장이 정상적으로 동작해도 운영 환경에서는 트래픽, 비용, 장애 대응까지 확인해야 합니다.

배포 전에 확인할 항목

  • Security Advisor에 해결하지 않은 항목이 있는가
  • 데이터베이스 사용량과 응답 속도를 확인하고 있는가
  • Auth, Storage, Edge Function 로그를 확인할 수 있는가
  • 사용량 한도와 초과 비용을 알고 있는가
  • 장애나 데이터 손실이 발생했을 때 대응 방법이 있는가
  • 프로젝트 소유자가 한 사람에게만 의존하고 있지 않은가

Security Advisor는 흔한 설정 문제를 찾는 데 도움이 되지만, 애플리케이션 전체의 보안을 보장하는 도구는 아닙니다. 실제 사용자 권한과 서비스 흐름은 별도로 테스트해야 합니다.

Supabase 운영 전 체크리스트


배포 전 최종 체크리스트

아래 항목만이라도 자신의 프로젝트에서 직접 확인해보세요.

  • 프론트엔드에는 공개용 키만 들어 있다
  • Secret key와 service_role key는 서버에서만 사용한다
  • 로그인과 데이터 권한을 별도로 구현했다
  • API에 노출된 모든 테이블의 RLS를 확인했다
  • 두 개 이상의 사용자 계정으로 권한을 테스트했다
  • Storage의 공개·비공개 범위를 구분했다
  • 입력값을 데이터베이스나 서버에서도 검증한다
  • 인증 Redirect URL과 요청 제한을 확인했다
  • 데이터베이스 변경사항을 Migration으로 관리한다
  • DB와 Storage의 백업 범위를 알고 있다
  • Security Advisor와 사용량을 주기적으로 확인한다

마무리

Supabase를 사용하면 백엔드 개발 시간을 크게 줄일 수 있습니다.

하지만 빠르게 구현할 수 있다는 것이 권한과 운영 설정까지 자동으로 해결된다는 뜻은 아닙니다.

처음부터 모든 것을 완벽하게 점검하기 어렵다면 우선 다음 세 가지부터 확인해보세요.

  1. 프론트엔드에 비밀 키가 포함되어 있지 않은가
  2. 다른 사용자의 데이터를 조회하거나 수정할 수 없는가
  3. 공개되면 안 되는 Storage 파일이 로그아웃 상태에서도 열리지 않는가

이 세 가지는 실제 프로젝트에 테스트 계정을 만들어 직접 확인할 수 있습니다.

설정 화면만 보고 안전하다고 판단하기보다, 권한이 다른 사용자의 입장에서 직접 요청해보는 과정이 필요합니다.

profile
꾸준히 기록 중 입니다.

0개의 댓글