Community코딩 & 개발github.com

supabase/supabase

Supabase 관련 모든 작업(데이터베이스, 인증, Edge Functions, Realtime, Storage, Vectors, Cron, 큐 등)에 사용합니다.

supabase란 무엇인가요?

이 스킬은 Supabase 플랫폼을 사용하는 모든 개발 작업을 지원하도록 설계된 포괄적인 가이드입니다. 데이터베이스, 인증, Edge Functions, Realtime, Storage, Vectors, Cron, 큐 등 Supabase의 모든 제품군을 다루며, Next.js, React, SvelteKit, Astro, Remix 환경에서 `supabase-js` 및 `@supabase/ssr` 같은 클라이언트 라이브러리와 SSR 통합을 지원합니다. 또한 Supabase CLI, MCP 서버, 스키마 변경, 마이그레이션, 보안 감사, Postgres 확장(pg_graphql, pg_cron, pg_vector) 관련 작업을 처리하며, HTTP 오류, Postgres 오류, RLS 문제, 권한 거부, 스키마 캐시 문제, 타임아웃, Edge Function 충돌, Realtime 연결 끊김, Storage 실패 등 다양한 문제를 디버깅하고 Logs Explorer와 ClickHouse를 통해 로그를 조회하는 방법을 제공합니다. 이 스킬은 변경이 잦은 Supabase의 특성을 반영하여 최신 문서 확인을 강조하고, RLS 보안, 인증, API 키 노출 방지 등 중요한 보안 체크리스트를 포함하여 안전한 애플리케이션 구축을 돕습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/supabase/agent-skills/tree/main/skills/supabase

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

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 클레임은 사용자 토큰이 갱신될 때까지 항상 최신 상태가 아닐 수 있음을 기억하세요.
  • 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'는 자동으로 중단됩니다. 익명 사용자는 authenticated Postgres 역할을 가지며 사용자가 실제로 로그인했는지 여부에 관계없이 검사를 통과하기 때문입니다.
      -- 더 이상 사용되지 않음 (사용 금지)
      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를 실행하세요.
  • 스토리지 액세스 제어

    • Storage upsert에는 INSERT + SELECT + UPDATE가 필요합니다. INSERT만 부여하면 새 업로드는 허용되지만 파일 교체(upsert)는 자동으로 실패합니다. 세 가지 모두 필요합니다.
  • 의존성 및 공급망 보안

    • Supabase 패키지(supabase-js, @supabase/ssr, supabase-py 등)를 설치할 때 항상 패키지 버전을 고정하고 잠금 파일을 커밋하세요. 전체 체크리스트는 npm 보안 가이드를 참조하세요.

위에서 다루지 않은 보안 관련 사항은 Supabase 제품 보안 인덱스를 가져오세요: https://supabase.com/docs/guides/security/product-security.md

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬