supabase은(는) 무엇을 하나요?
핵심 원칙
1. Supabase는 자주 변경됩니다 — 구현 전에 변경 로그와 최신 문서를 확인하세요.
Supabase 기능에 대해 훈련 데이터에 의존하지 마세요. 함수 시그니처, config.toml 설정, API 규칙은 버전 간에 변경됩니다.
먼저 https://supabase.com/changelog.md (가벼운 요약 인덱스 — 무거운 풀링이 아님)를 가져와서, 작업과 관련된 breaking-change 태그를 스캔하고, 해당하는 경우 링크된 페이지를 따르세요. 그런 다음 아래 문서 접근 방법을 사용하여 관련 주제를 찾아보세요.
2. 작업을 검증하세요. 수정을 구현한 후, 테스트 쿼리를 실행하여 변경 사항이 작동하는지 확인하세요. 검증 없는 수정은 불완전합니다.
3. 오류에서 복구하고, 반복하지 마세요. 접근 방식이 2-3회 시도 후에도 실패하면 중단하고 재고하세요. 다른 방법을 시도하고, 문서를 확인하고, 오류를 더 주의 깊게 검사하고, 가능할 때 관련 로그를 검토하세요. Supabase 문제는 항상 같은 명령어를 재시도함으로써 해결되는 것이 아니며, 답이 항상 로그에 있는 것은 아니지만, 진행하기 전에 로그를 확인하는 것이 종종 가치 있습니다.
4. Data API에 테이블 노출: 사용자의 Data API 설정에 따라, 새로 생성된 테이블이 Data (REST) API를 통해 자동으로 노출되지 않을 수 있습니다. 이 경우 anon 및 authenticated 역할에 명시적으로 액세스 권한을 부여해야 합니다.
이는 RLS와 별개입니다. RLS는 테이블에 접근 가능할 때 어떤 _행_이 보이는지를 제어하며, 테이블 자체에 접근 가능한지 여부는 제어하지 않습니다.
사용자가 SQL로 생성한 테이블에 예기치 않게 접근할 수 없다고 보고하면, Data API 설정과 명시적 GRANT SQL을 통해 역할에 액세스 권한이 부여되었는지 확인하세요. 공개(anon/authenticated) 액세스를 부여할 때는 항상 RLS도 활성화하세요. 전체 설정 워크플로는 Data API에 테이블 노출을 참조하세요.
5. 노출된 스키마의 RLS.
기본적으로 public을 포함하여 노출된 모든 스키마의 모든 테이블에서 RLS를 활성화하세요. Supabase에서는 anon/authenticated 역할이 액세스 권한을 가질 때 노출된 스키마의 테이블이 Data API를 통해 접근 가능할 수 있으므로 이는 중요합니다(Data API에 테이블 노출 참조). 비공개 스키마의 경우 심층 방어로서 RLS를 선호하세요. RLS를 활성화한 후에는 모든 테이블에 동일한 auth.uid() 패턴을 기본값으로 사용하지 말고 실제 액세스 모델과 일치하는 정책을 만드세요.
6. 보안 체크리스트. 인증, RLS, 뷰, 스토리지 또는 사용자 데이터를 다루는 Supabase 작업을 수행할 때는 이 체크리스트를 실행하세요. 이는 자동으로 취약점을 생성하는 Supabase 특정 보안 함정입니다.
-
인증 및 세션 보안
- JWT 기반 인가 결정에
user_metadata클레임을 절대 사용하지 마세요. Supabase에서raw_user_meta_data는 사용자가 편집 가능하며auth.jwt()에 나타날 수 있으므로 RLS 정책이나 다른 인가 로직에 사용하기에 안전하지 않습니다. 대신raw_app_meta_data/app_metadata에 인가 데이터를 저장하세요. - 사용자를 삭제해도 기존 액세스 토큰이 무효화되지 않습니다. 먼저 로그아웃하거나 세션을 취소하고, 민감한 앱의 경우 JWT 만료 시간을 짧게 유지하며, 엄격한 보장을 위해 민감한 작업에서
session_id를auth.sessions에 대해 검증하세요. - 인가를 위해
app_metadata또는auth.jwt()를 사용하는 경우, JWT 클레임은 사용자 토큰이 갱신될 때까지 항상 최신 상태가 아닐 수 있음을 기억하세요.
- JWT 기반 인가 결정에
-
API 키 및 클라이언트 노출
- 공개 클라이언트에서
service_role또는 시크릿 키를 절대 노출하지 마세요. 프론트엔드 코드에는 공개 가능한 키를 선호하세요. 레거시anon키는 호환성용입니다. Next.js에서NEXT_PUBLIC_접두사가 붙은 모든 환경 변수는 브라우저로 전송됩니다.
- 공개 클라이언트에서
-
RLS, 뷰 및 권한 있는 데이터베이스 코드
- 뷰는 기본적으로 RLS를 우회합니다. Postgres 15 이상에서는
CREATE VIEW ... WITH (security_invoker = true)를 사용하세요. 이전 Postgres 버전에서는anon및authenticated역할의 액세스를 취소하거나 노출되지 않은 스키마에 배치하여 뷰를 보호하세요. - UPDATE에는 SELECT 정책이 필요합니다. Postgres RLS에서 UPDATE는 먼저 행을 SELECT해야 합니다. SELECT 정책이 없으면 업데이트는 자동으로 0행을 반환합니다 — 오류 없이 변경되지 않습니다.
auth.role()은 더 이상 사용되지 않습니다 — 대신TO절을 사용하세요. Supabase는TO authenticated또는TO anon과 같이 정책에서 대상 역할을 직접 지정하는 것을 위해auth.role()을 더 이상 사용하지 않습니다. 더 이상 사용되지 않는 것 외에도, 익명 로그인이 활성화되면auth.role() = 'authenticated'는 자동으로 중단됩니다. 익명 사용자는authenticatedPostgres 역할을 가지며 사용자가 실제로 로그인했는지 여부에 관계없이 검사를 통과하기 때문입니다.-- 더 이상 사용되지 않음 (사용 금지) create policy "example" on table_name for select using ( auth.role() = 'authenticated' );TO authenticated만으로는 인증 없이 인가가 없습니다 (BOLA / IDOR).TO authenticated를 사용하는 것은 역할만 확인합니다 — 사용자가 어떤 행에 접근할 수 있는지 제한하지 않습니다. 올바른 패턴은TO authenticated를USING의 소유권 조건과 결합하는 것입니다:create policy "example" on table_name for select to authenticated using ( (select auth.uid()) = user_id );- UPDATE 정책은
USING과WITH CHECK가 모두 필요합니다.WITH CHECK가 없으면 사용자가 행의user_id를 다른 사용자로 재할당할 수 있습니다:create policy "example" on table_name for update to authenticated using ( (select auth.uid()) = user_id ) with check ( (select auth.uid()) = user_id ); SECURITY DEFINER함수는 RLS를 우회합니다.SECURITY DEFINER함수는 생성자의 권한으로 실행됩니다 — 일반적으로bypassrls가 있는 역할(예:postgres)입니다. 권한 오류를 해결하기 위해SECURITY DEFINER를 절대 추가하지 마세요. 이는 근본 원인을 해결하지 않고 자동으로 액세스 제어를 제거합니다.SECURITY INVOKER를 선호하세요.public의SECURITY DEFINER함수는 모든 역할이 호출할 수 있습니다. Postgres는 모든 새 함수에 대해 기본적으로PUBLIC에EXECUTE를 부여하므로public의SECURITY DEFINER함수는 추가 GRANT 없이anon및authenticated(PUBLIC에서 상속)가 호출할 수 있는 공개 API 엔드포인트입니다.SECURITY DEFINER가 실제로 필요한 경우(예: 내부 조회 테이블에서 RLS 우회), 함수를 노출되지 않은 스키마에 유지하고, 함수 본문에 항상auth.uid()검사를 포함하며, 변경 후supabase db advisors를 실행하세요.
- 뷰는 기본적으로 RLS를 우회합니다. Postgres 15 이상에서는
-
스토리지 액세스 제어
- Storage upsert에는 INSERT + SELECT + UPDATE가 필요합니다. INSERT만 부여하면 새 업로드는 허용되지만 파일 교체(upsert)는 자동으로 실패합니다. 세 가지 모두 필요합니다.
-
의존성 및 공급망 보안
- Supabase 패키지(
supabase-js,@supabase/ssr,supabase-py등)를 설치할 때 항상 패키지 버전을 고정하고 잠금 파일을 커밋하세요. 전체 체크리스트는 npm 보안 가이드를 참조하세요.
- Supabase 패키지(
위에서 다루지 않은 보안 관련 사항은 Supabase 제품 보안 인덱스를 가져오세요: https://supabase.com/docs/guides/security/product-security.md