본문으로 건너뛰기
5분 AI.
GITHUB TRENDING DAILY #6 딥다이브 · 2026-10-23 분석

supabase 딥다이브
— 데이터베이스 하나를 개발 플랫폼으로 만드는 설계

백엔드 플랫폼

빠른 판단

무엇
PostgreSQL에 데이터 API·인증·파일 저장·실시간 통신·Studio를 연결한 앱 백엔드 플랫폼
이럴 때
관계형 데이터를 중심으로 웹·모바일·AI 앱을 만들며 로그인·권한·스토리지·실시간 기능을 함께 구성할 때
테이블을 만들면 API가 생기고, 로그인한 사용자의 데이터 권한은 데이터베이스가 판단합니다. Supabase는 PostgreSQL에 인증·파일 저장·실시간 통신·함수 실행을 연결한 개발 플랫폼입니다. 이 글은 Studio의 조회 코드부터 SQL 조립기, Docker 서비스 구성까지 따라가며 여러 도구를 하나의 제품으로 묶는 방법을 배웁니다. 저장소: supabase/supabase · ⭐113,641 · 포크 17,020 · TypeScript · Apache-2.0 · 2026-10-23 GitHub 기준.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

PostgreSQL을 중심으로 백엔드의 공통 기능을 연결하는 플랫폼

Supabase를 한 문장으로 말하면 PostgreSQL 데이터베이스를 웹·모바일·AI 앱에서 바로 쓰도록 주변 기능을 묶은 플랫폼입니다. 데이터는 PostgreSQL에 저장하고, PostgREST는 테이블·뷰·함수를 HTTP API로 노출합니다. Auth는 로그인과 토큰을 담당하고, Storage와 Realtime은 파일과 실시간 연결을 맡습니다.

이 저장소에서 배울 핵심은 데이터베이스를 만드는 법보다, 데이터베이스 주변의 도구들을 일관된 개발 경험으로 연결하는 법입니다. apps/studio에는 관리 화면이, packages/pg-meta에는 데이터베이스 구조를 읽는 SQL 조립기가, docker에는 서비스들을 연결하는 설정이 있습니다.

비유로 이해하기

PostgreSQL이 건물이라면, Supabase는 운영 설비입니다

데이터베이스는 기록을 보관하는 건물입니다. Auth는 신분 확인 창구, RLS는 방마다 붙은 출입 규칙, PostgREST는 서류 접수 창구, Realtime은 변경 사항을 알리는 방송입니다.

Studio는 관리실입니다. 관리실에서 장부를 살펴보는 동선과, 일반 방문자가 자기 서류를 읽는 동선은 서로 다릅니다. 이 차이가 뒤의 아키텍처를 이해하는 출발점입니다.

용어 풀이
BaaS · 백엔드 서비스형 플랫폼
회원가입, 데이터 저장, 파일 업로드처럼 여러 앱에 반복되는 서버 기능을 공통 서비스로 제공하는 방식입니다. 제품 개발자는 화면과 업무 규칙에 집중할 수 있지만, 데이터 모델과 접근 권한은 여전히 설계해야 합니다.

제품 전체와 이 저장소의 범위를 구분하기

구분이 저장소에서 확인하는 것별도로 살펴볼 것
관리 경험Studio 화면, 조회 훅, 서버 API, 공유 UI호스팅 플랫폼의 모든 운영 내부 구현
데이터베이스카탈로그 조회 SQL, 마이그레이션, Docker 연결PostgreSQL 엔진과 확장 자체의 구현
인증·실시간·저장소서비스 이미지, 환경 변수, 예제와 문서Auth·Realtime·Storage 각각의 별도 저장소
클라이언트 SDKSDK를 사용하는 앱과 예제supabase/supabase-js의 SDK 내부

README.md는 제품 전체의 기능을 소개합니다. 반면 루트 package.json의 작업 대상은 pnpm과 Turborepo로 관리하는 앱·패키지입니다. 따라서 GitHub의 주 언어가 TypeScript라는 사실을 PostgreSQL이나 모든 서비스의 구현 언어로 확대하면 안 됩니다.

2왜 주목받는가

빠른 개발 경험과 관계형 데이터 모델을 함께 공부할 수 있다

2026-10-23 GitHub Trending Daily에서 6위에 선정됐고, 같은 날짜 기준 스타는 113,641개입니다. 이 수치는 관심의 크기를 보여주지만 그날의 순위 상승 원인을 설명하지는 않습니다. 여기서는 저장소에 포함된 앱과 코드에서 읽을 수 있는 장점을 살펴봅니다.

저장소에 포함된 지식 기반 앱

커밋 2f548a69에는 Knowledge Base 앱이 포함돼 있습니다. 오류 해결과 다른 플랫폼에서의 이전 안내를 모은 지식 기반입니다. apps/kb/package.json에는 Astro 의존성과 콘텐츠 생성 스크립트가 있습니다. 이 앱의 존재만으로 트렌딩 순위의 원인을 설명할 수는 없습니다. Knowledge Base 구현과 콘텐츠.

개발자가 관심을 가질 만한 세 가지 이유

관계형 모델

SQL 지식이 플랫폼 밖에서도 남는다

테이블, 외래 키, 인덱스, 트랜잭션을 직접 배웁니다. 관리 화면이 대신 처리하는 동작도 결국 SQL과 PostgreSQL 카탈로그로 내려가므로, 화면 사용법에서 데이터베이스 원리로 학습을 확장할 수 있습니다.

개발 속도

반복되는 API와 인증 연결 작업을 줄인다

docker/docker-compose.yml은 PostgREST·Auth·Storage 등을 이미 연결합니다. CRUD마다 라우트를 새로 만드는 부담이 줄어드는 대신, 노출할 스키마·역할·행 정책을 올바르게 설정하는 능력이 중요해집니다.

운영 선택권

서비스 구성을 열어 보고 자체 호스팅할 수 있다

이미지 태그, 볼륨, 상태 검사, 프록시 경로를 읽을 수 있습니다. 자체 호스팅은 인프라 통제권을 주지만, 백업·업데이트·비밀 값 관리도 운영자의 책임이 됩니다. 클라우드의 모든 기능이 동일하게 재현된다는 뜻은 아닙니다.

다른 선택지와 비교하면 어디가 다른가

선택지출발하는 모델Supabase에서 배울 차이
SupabasePostgreSQL 테이블·SQL·역할관계형 모델, 자동 API, 데이터베이스 권한을 한 흐름으로 연결
Cloud Firestore문서와 컬렉션을 중심으로 한 NoSQL 모델문서 중첩과 테이블 관계의 설계 차이를 비교하기 좋음
직접 SQL 연결연결 문자열과 SQL로 데이터베이스에 접근HTTP API와 인증 계층이 어느 위치에 추가되는지 비교
직접 만든 API 서버팀이 라우트·쿼리·권한 경계를 직접 구현자동화할 공통 기능과 직접 작성할 업무 로직의 경계를 판단

비교 범위는 데이터 접근 모델입니다. Firebase 전체를 문서형 데이터베이스 하나로 규정하지 않습니다. Firestore의 문서·컬렉션 모델은 저장소의 Firebase 비교 문서, SQL 연결 구성은 docker/docker-compose.yml을 기준으로 설명합니다. 성능·가격의 우열을 측정한 비교는 아닙니다.

Supabase의 장점은 SQL을 감추는 데 있지 않고, SQL과 권한 모델을 유지하면서 앱 개발에 필요한 연결 작업을 줄이는 데 있습니다.

3기술 스택 전체 지도

앱 의존성, 실행 이미지, 예제의 언어를 서로 구분해서 읽기

버전의 기준은 커밋 2f548a69입니다. package.json의 catalog:는 중앙 버전표를 가리키며, 실제 범위는 pnpm-workspace.yaml에서 찾습니다. 설치 해석 결과는 pnpm-lock.yaml의 catalogs.default에 기록돼 있습니다.

용어 풀이
버전 범위와 잠금 파일
^8.0.16은 허용할 버전 범위이고 8.2.1은 잠금 파일에 선택된 구체 버전입니다. 여러 앱이 같은 중앙 표를 참조하면 중복 설정을 줄이고 함께 업데이트하기 쉽습니다.

프론트엔드: Studio와 문서·지식 기반

기술선언 / 잠금 버전역할과 근거
React^19.2.6 / 19.2.6화면 구성. 중앙 catalog와 Studio의 react 의존성
Next.js^16.3.6 / 16.3.6Studio 기본 실행 경로와 Docs. apps/studio/scripts/dispatch.js
TanStack Start^1.169.2 / 1.169.2Studio의 병행 전환 경로. Router는 ^1.170.44 / 1.170.44
TanStack QueryStudio 선언 ~5.104.3서버 조회·캐시·무효화. apps/studio/package.json
Tailwind CSS^4.2.4 / 4.2.4공유 UI와 화면 스타일. 중앙 catalog
Valtio · Zod^2.3.2 / 2.3.2 · 3.25.76공유 상태와 데이터 구조 정의. Studio 의존성과 catalog
Vite^8.0.16 / 8.2.1TanStack 실행 경로 등. 선언과 잠금 결과의 차이가 보이는 예
AstroKB 선언 ^7.2.6지식 기반 사이트. apps/kb/package.json

apps/lite-studio는 별도의 경량 앱입니다. apps/lite-studio/package.json에는 react-router: ^7.17.0과 vite: ^8.0.0이 선언돼 있습니다. 같은 모노레포라고 모든 앱이 Next.js로 실행되는 것은 아닙니다.

백엔드: Docker가 조합하는 여러 서비스

다음은 docker/docker-compose.yml의 이미지 태그입니다. 패키지 버전이나 제품 전체 릴리스 번호와 다른 축입니다. 각 엔진의 내부 소스가 이 저장소에 전부 들어 있다는 뜻도 아닙니다.

서비스실제 이미지담당하는 일
PostgreSQLsupabase/postgres:17.6.1.136관계형 데이터, 역할, 정책, 확장
API 게이트웨이envoyproxy/envoy:v1.39.1외부 경로를 내부 서비스로 연결
Authsupabase/gotrue:v2.197.0회원가입·로그인·JWT 발급
REST APIpostgrest/postgrest:v14.18데이터베이스 객체를 HTTP 자원으로 제공
Realtimesupabase/realtime:v2.143.3실시간 구독과 통신
Storagesupabase/storage-api:v1.81.0파일 API와 접근 제어 연결
postgres-metasupabase/postgres-meta:v0.100.0데이터베이스 구조와 관리 쿼리 API
Edge Runtimesupabase/edge-runtime:v1.77.4Deno 기반 함수 실행 환경
Supavisorsupabase/supavisor:2.9.13데이터베이스 연결 풀링
imgproxydarthsim/imgproxy:v3.31.4이미지 변환

Storage의 기본 설정은 STORAGE_BACKEND: file, 파일 크기 제한은 52428800바이트, 즉 50 MiB입니다. README의 S3 중심 설명과 달리 기본 Compose는 로컬 파일 저장을 사용하며, S3 계열 구성은 별도 덮어쓰기 파일로 선택합니다. 이런 차이가 설정 파일을 읽어야 하는 이유입니다.

docker/README.md의 구성 소개에는 Logflare와 Vector도 등장합니다. 실제 기본 Compose에는 없으며 docker/docker-compose.logs.yml로 추가합니다. 이때 Logflare 이미지 태그는 1.50.15이고 Studio의 ENABLED_FEATURES_LOGS_ALL이 true로 바뀝니다.

인프라·빌드: 버전을 묶고 작업 순서를 관리한다

항목설정값읽을 파일
Node.jsengines.node: >=22.13, .nvmrc: 22루트 package.json · .nvmrc
pnpmpackageManager: pnpm@11.13.1루트 package.json
Turborepo2.9.14, 빌드 선행 작업 ^buildpackage.json · turbo.jsonc
TypeScript 도구typescript: ~6.0.2, @typescript/native: npm:typescript@~7.0.2중앙 catalog. API 호환 패키지와 네이티브 컴파일러를 나눔
Vitest^5.0.0 / 5.0.0catalog · Studio의 test:ci
Docker 빌드node:22-slim, turbo prune studio --dockerapps/studio/Dockerfile

Dockerfile은 의존성 가지치기, 설치, 프레임워크별 빌드, 실행 산출물 복사를 단계로 나눕니다. 최종 서버 포트는 3000입니다. STUDIO_FRAMEWORK 선택은 이미지 빌드 시점에 적용됩니다. 실행 중인 이미지에서 환경 변수만 바꿔 두 프레임워크를 즉시 전환하는 구조가 아닙니다.

.github/workflows/typecheck.yml은 잠금 파일 고정 설치 후 같은 작업 안에서 타입 검사와 린트를 병렬 단계로 수행합니다. .github/workflows/studio-unit-tests.yml은 관련 경로 변경을 필터링하고, .github/workflows/studio-lint-ratchet.yml은 선택한 규칙의 위반 수 증가를 막습니다. 기존 경고를 한 번에 없애기 어려운 큰 프로젝트의 점진적 품질 관리 사례입니다.

Python과 Rust는 어디에 있는가

examples/ai/image_search/pyproject.toml은 Python ^3.11, sentence-transformers ^2.7.0, vecs ^0.2.4를 선언합니다. examples/edge-functions/supabase/functions/wasm-modules/add-wasm/Cargo.toml은 Rust 2021 edition, cdylib, wasm-bindgen 0.2를 사용합니다. 둘 다 예제의 의존성입니다. 추적 파일에서 go.mod는 발견되지 않았습니다.

기술 스택을 읽을 때는 웹앱의 패키지, 서비스의 이미지 태그, 예제의 도구 버전을 각각의 범위 안에서 해석해야 합니다.

4아키텍처 심화 분석

일반 앱의 데이터 경로와 Studio의 관리 경로를 함께 따라가기

아래 도식은 docker/docker-compose.yml과 게이트웨이 설정을 바탕으로 단순화한 자체 호스팅 구조입니다. 각 선이 별도의 네트워크 호출이나 데이터 접근 경계를 뜻합니다. 클라우드의 모든 내부 제어 계층을 묘사한 그림은 아닙니다.

일반 웹·모바일 앱 / SDK | v Envoy API 게이트웨이 :8000 | +-- /auth/v1/* -----> Auth -----------+ +-- /rest/v1/* -----> PostgREST ------+ +-- /graphql/v1 ---> PostgREST RPC ---+--> PostgreSQL +-- /realtime/v1/* -> Realtime -------+ 데이터·역할·RLS +-- /storage/v1/* --> Storage --------+ ^ | | | | +--> 파일 볼륨 / imgproxy | +-- /functions/v1/* -> Edge Runtime --> 사용자 함수 | +-- / -------------> Studio 관리 화면 | v Studio 서버 API | v postgres-meta ------------> DB 별도 SQL 클라이언트 ----> Supavisor 연결 풀 ----> PostgreSQL 선택 구성: 로그 수집 Vector ----> Logflare ----> Studio 로그 화면

GraphQL 경로는 게이트웨이에서 /rpc/graphql로 바뀌어 PostgREST로 전달됩니다. docker/volumes/api/envoy/lds.template.yaml의 graphql-v1-protected 경로에서 이 연결을 읽을 수 있습니다. GraphQL 전용 서버가 무조건 하나 더 떠 있는 구조로 상상하지 않아도 됩니다.

패턴 1. 입구는 통합하고 책임은 서비스별로 나눈다

API 게이트웨이 패턴은 외부 주소 체계와 내부 서비스 배치를 분리합니다. docker/volumes/api/envoy/lds.template.yaml에는 경로 조건, 대상 cluster, 접두 경로 변환이 있고, docker/volumes/api/envoy/cds.yaml에는 대상 호스트·포트·연결 제한·상태 검사가 있습니다.

# docker/volumes/api/envoy/lds.template.yaml 중 경로 구조 발췌
match:
  prefix: /rest/v1/
route:
  cluster: rest
  prefix_rewrite: /

# docker/volumes/api/envoy/cds.yaml의 rest 대상: rest:3000
# 외부 /rest/v1/todos 요청은 내부 /todos로 전달된다.

Envoy의 경로 설정은 WebSocket 업그레이드를 허용하고 Realtime 경로를 /socket/ 쪽으로 보냅니다. 프록시가 단순히 문자열만 바꾸는 것이 아니라 각 서비스의 통신 방식까지 연결한다는 점을 배울 수 있습니다.

관리용 SQL 경로는 일반 데이터 API와 다르다

apps/studio/data/sql/execute-sql-mutation.ts의 executeSql()은 공통 조회 전송 경계입니다. 프로젝트 식별자를 검사하고, SQL 크기를 0.98 * MB와 비교하며, 연결 정보와 요청 옵션을 붙입니다.

useSchemasQuery() -> getSchemas() -> executeSql({ sql: pgMetaSchemasList.sql }) -> post('/platform/pg-meta/{ref}/query', ...) -> 자체 호스팅의 Studio API handlePost() -> 서버 executeQuery() -> postgres-meta /query -> PostgreSQL

자체 호스팅 서버 진입점은 apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts의 handlePost()입니다. 이어지는 apps/studio/lib/api/self-hosted/query.ts의 executeQuery()는 assertSelfHosted()를 호출하고, 연결 문자열을 암호화한 헤더와 함께 pg-meta로 보냅니다.

apps/studio/data/fetchers.ts의 createClient<paths>()는 OpenAPI 타입을 사용합니다. constructHeaders()는 요청 ID와 인증 헤더를 구성하고, pgMetaGuard()는 플랫폼 환경에서 필요한 연결 헤더를 검사합니다. 호출마다 이 처리를 복제하지 않도록 한곳에 모은 설계입니다.

권한 경계
관리 화면의 동작을 일반 사용자의 권한 검증으로 착각하지 않기

자체 호스팅 Compose는 pg-meta의 DB 사용자에 postgres를 설정합니다. 관리자 경로와 앱 사용자의 RLS 경로는 권한이 다릅니다. 관리 화면에서 보인다는 이유만으로 일반 사용자가 같은 행을 읽을 수 있다고 판단하면 안 됩니다.

패턴 2. 조회 함수와 화면의 캐시 생명주기를 분리한다

apps/studio/data/database/schemas-query.ts에는 getSchemas(), useSchemasQuery(), invalidateSchemasQuery(), prefetchSchemas()가 함께 있습니다. 하나의 자원을 가져오는 방법을 정의하고, 화면·사전 조회·갱신이 그 정의를 재사용합니다.

// apps/studio/data/database/keys.ts의 키 구조
const key = ['projects', projectRef, 'schemas'] as const

// apps/studio/data/database/schemas-query.ts의 핵심 옵션을 줄여 쓴 학습용 예
useQuery({
  queryKey: databaseKeys.schemas(projectRef),
  queryFn: ({ signal }) =>
    getSchemas({ projectRef, connectionString }, signal),
  enabled: enabled && typeof projectRef !== 'undefined',
})

키에 projectRef가 있으므로 서로 다른 프로젝트의 스키마 목록이 같은 캐시 자리에 들어가지 않습니다. AbortSignal을 전달하는 흐름은 필요 없어진 요청을 취소할 통로를 만들고, enabled는 프로젝트가 정해지기 전의 조회를 막습니다.

비유로 이해하기

캐시 키는 서류 보관함의 주소입니다. 서랍 이름이 모두 ‘스키마’라면 어느 프로젝트 서류인지 헷갈립니다. ‘프로젝트 → 식별자 → 스키마’로 주소를 만들면 올바른 서랍을 읽고 비울 수 있습니다.

여기서 한 단계 더 읽어야 합니다. Schema와 SchemasData는 Zod 스키마로부터 타입을 추론하지만, 이 파일의 getSchemas()는 응답에 zod.parse()를 호출하지 않습니다. 실제 처리는 Array.isArray(result) 검사입니다. 타입 선언이 있다는 사실과 모든 응답 필드가 런타임에 검증된다는 주장은 다릅니다.

패턴 3. SQL의 신뢰 경계를 타입으로 표시한다

packages/pg-meta/src/pg-format/index.ts는 일반 문자열과 안전하게 조립할 SQL 조각을 구분합니다. SafeSqlFragment는 문자열에 식별용 타입 표식을 더한 브랜드 타입입니다. 표식은 컴파일 시점의 규칙이며, 별도의 암호학적 검증 값이 아닙니다.

// 타입 구조와 사용법을 보여주는 학습용 예
type SafeSqlFragment = string & {
  readonly __safeSqlFragmentBrand: never
}

const table = ident('user notes')
const owner = literal("O'Reilly")
const sql = safeSql`select * from ${table} where owner = ${owner}`

// 결과: select * from "user notes" where owner = 'O''Reilly'
// safeSql`select * from ${userInput}`
// 일반 string을 그대로 끼우면 타입 규칙에 어긋난다.
함수입력의 의미설계 의도
ident()테이블·열·스키마 같은 이름SQL 식별자의 인용 규칙을 적용
literal()문자열·숫자·NULL 같은 값값에 맞는 SQL 표현을 생성
safeSql이미 안전한 조각들삽입 인수를 SafeSqlFragment로 제한하여 조합
untrustedSql()외부 내용의 영향을 받은 SQL표시는 허용하되 자동 실행과 구분
acceptUntrustedSql()명시적으로 승인된 편집기 SQL사용자 실행 동작에서 신뢰 경계를 넘김

실제 safeSql() 구현은 문자열을 이어 붙입니다. 이 함수 자체가 모든 입력을 정제하는 것은 아닙니다. ident()·literal()로 의미에 맞게 변환한 뒤 조합하는 규칙이 중요하며, rawSql()이나 강제 타입 단언을 남용하면 보호를 우회할 수 있습니다.

packages/pg-meta/README.md는 SQL 조각을 매개변수화됐다고 소개하지만, 여기서 본 조립기는 주로 값을 이스케이프한 SQL 문자열을 만듭니다. 일반적인 $1 자리표시자와 값 배열을 전송하는 준비된 쿼리와 동일한 구현이라고 설명하면 부정확합니다. 서버 executeQuery()가 별도 parameters 옵션을 지원하는 점과도 구분해야 합니다.

패턴 4. 성능 요구사항을 실행 계획의 규칙으로 만든다

packages/pg-meta/src/sql/studio/table-editor/table.ts의 getTableEditorSql({ id })는 테이블 정보를 여러 CTE로 묶습니다. base_table_info는 c.oid, primary_keys와 index_cols는 i.indrelid를 요청한 테이블 ID로 제한합니다.

-- getTableEditorSql()의 필터 구조를 줄인 예
with base_table_info as (
  select c.oid, c.relname
  from pg_class c
  where c.oid = 12345
), primary_keys as (
  select i.indrelid
  from pg_index i
  where i.indisprimary and i.indrelid = 12345
)
select * from base_table_info;

테이블 하나를 열 때마다 전체 데이터베이스의 인덱스·제약 조건을 모두 훑으면, 사용자 테이블 수가 많아질수록 관리 화면도 느려집니다. 그래서 결과 값만 맞는지 검사하는 테스트에 더해 어떤 경로로 읽는지를 검사합니다.

packages/pg-meta/test/db/plan-guard.ts의 explainAnalyze()는 EXPLAIN (ANALYZE, FORMAT JSON)을 사용합니다. collectSeqScans()는 계획 트리의 Seq Scan 노드별 관계 이름을 모으고, assertPlanWithinBudget()는 허용 목록·노드 수·실행 시간을 검사합니다. 기본 시간 예산은 1000ms입니다.

packages/pg-meta/test/sql/studio/catalog-plan-guard.test.ts는 합성 카탈로그를 만들고 이 규칙을 적용합니다. 예를 들어 테이블 편집기 예산은 역방향 외래 키 조회의 구조적 이유를 적고 pg_constraint의 Seq Scan 노드를 최대 2개 허용합니다. ‘순차 탐색은 전부 나쁘다’가 아니라, 불가피한 탐색의 이유와 한도를 코드에 남깁니다.

배울 설계 원칙
회귀를 막을 조건을 기계가 검사하게 만든다

기능이 맞는지, 권한이 맞는지, 규모가 커져도 접근 범위가 맞는지는 서로 다른 질문입니다. 성능 문제를 고친 뒤 실행 계획 규칙을 테스트에 넣으면, 다음 변경에서 같은 문제가 돌아오는지 확인할 수 있습니다.

Studio의 executeSql()에도 선택적 preflightCheck가 있습니다. 예상 비용이 200_000 이상이면 차단합니다. 사전 검사 응답의 오류 필드는 무시하지만, 네트워크 예외 등을 잡는 처리는 없습니다. PostgreSQL의 예상 비용은 밀리초가 아니며, 이 선택적 장치를 데이터베이스 전체의 보안·부하 보장으로 해석해서는 안 됩니다.

좋은 추상화는 세부 사항을 지우는 것이 아니라, 요청·권한·SQL·성능의 경계를 읽을 수 있는 위치에 모아 둡니다.

5디렉토리 구조 해부

폴더 이름을 외우기보다 변경이 흐르는 방향을 찾는다
supabase/ +-- apps/ | +-- studio/ 관리 화면과 서버 API | | +-- pages/ Next.js 페이지와 API | | +-- routes/ TanStack Start 라우트 | | +-- data/ 자원별 조회·변경·캐시 키 | | +-- components/ 화면 구성 요소 | | +-- lib/ API·SQL·인증 관련 공통 로직 | | +-- scripts/ 실행 경로 선택 등 개발 도구 | +-- docs/ 공식 문서 사이트와 MDX 원문 | +-- www/ 제품·마케팅 사이트 | +-- kb/ 오류 해결·이전 지식 기반 | +-- lite-studio/ 별도 경량 관리 앱 | +-- design-system/ 디자인 시스템 예시 | +-- ui-library/ 재사용 UI 블록 사이트 | +-- learn/ 학습 콘텐츠 사이트 +-- packages/ | +-- pg-meta/ 카탈로그 SQL 조립기와 테스트 | +-- ui/ 기본 UI 구성 요소 | +-- ui-patterns/ 여러 UI를 묶은 공통 패턴 | +-- common/ 공유 도구·기능 플래그 등 | +-- api-types/ 플랫폼 API 타입과 생성 도구 | +-- shared-data/ 요금제·리전 등 공통 정적 데이터 +-- docker/ 자체 호스팅 구성·볼륨·상태 검사 +-- examples/ 인증·저장소·실시간·AI 예제 +-- blocks/ Vue용 재사용 블록 +-- e2e/ 브라우저 기반 통합 검사 +-- supabase/ 이 모노레포의 함수·마이그레이션 +-- .github/workflows/ 변경 경로별 자동 검사 +-- pnpm-workspace.yaml 작업공간 범위와 중앙 의존성 +-- pnpm-lock.yaml 의존성 해석 결과 +-- turbo.jsonc 작업 순서와 캐시 설정
학습하고 싶은 것첫 번째 파일다음 이동
목록 조회와 캐시apps/studio/data/database/schemas-query.tsapps/studio/data/database/keys.ts → apps/studio/data/sql/execute-sql-mutation.ts
SQL 조립 안전성packages/pg-meta/src/pg-format/index.tspackages/pg-meta/src/pg-meta-schemas.ts → SQL 생성 함수
테이블 편집기 원리packages/pg-meta/src/sql/studio/table-editor/table.tspackages/pg-meta/test/sql/studio/catalog-plan-guard.test.ts
서비스 연결docker/docker-compose.ymldocker/volumes/api/envoy/lds.template.yaml → docker/volumes/api/envoy/cds.yaml
함수 실행 제한docker/volumes/functions/main/index.tsCompose의 functions 서비스
단계적 프레임워크 전환apps/studio/scripts/dispatch.jsapps/studio/TANSTACK_MIGRATION.md → apps/studio/pages/와 apps/studio/routes/

루트의 supabase/는 Supabase 제품 전체의 모든 서버 코드라는 뜻이 아닙니다. 이 모노레포에서 사용하는 로컬 프로젝트 설정, 함수, 마이그레이션이 모여 있습니다. 한편 docker/는 배포 구성이고, packages/pg-meta는 SQL 생성 라이브러리입니다. 폴더가 다루는 책임을 먼저 구분하면 탐색 범위를 크게 줄일 수 있습니다.

읽는 순서

한 화면의 조회 훅을 출발점으로 삼아 ‘데이터를 요청하는 곳 → 전송 경계 → 서버 처리 → SQL 생성’으로 이동하세요. 모노레포 전체를 첫 파일부터 순서대로 읽으려 하면 사용자 동작과 코드의 연결을 놓치기 쉽습니다.

6학습 포인트 (기술별)

도구 이름마다 배울 개념 하나와 작은 연습 하나를 연결한다

TypeScript: ‘문자열’보다 좁은 의미를 모델링하기

SafeSqlFragment와 UntrustedSqlFragment는 같은 문자열도 출처와 허용 동작에 따라 다르게 취급하는 예입니다. 또 apps/studio/data/query-sources/query-source-registry.ts는 _tag: 'database' | 'logs'로 데이터 원본을 구분합니다. 각 SQL 방언과 전송 경계를 잘못 섞지 않도록 유니온 타입을 사용합니다.

연습: 문자열 하나로 표현하던 값을 ‘사용자가 작성한 SQL’과 ‘외부에서 들어온 SQL’로 나누어 종이에 타입을 설계해 보세요. 어떤 함수가 표시만 허용하고 어떤 함수가 실행을 허용해야 하는지 화살표로 표시하면 타입의 목적을 이해할 수 있습니다.

React와 TanStack Query: 서버 상태와 화면 상태를 분리하기

스키마 목록은 서버에서 받은 상태이고, 펼쳐 둔 메뉴는 화면 상태입니다. 둘을 같은 방식으로 관리할 필요는 없습니다. useSchemasQuery()는 조회 키·활성 조건·취소 신호를 묶어 서버 상태를 다룹니다. getSchemas()를 별도 함수로 둬 React 바깥의 사전 조회에서도 재사용합니다.

연습: ‘프로젝트 A의 테이블 목록’과 ‘프로젝트 B의 테이블 목록’의 캐시 키를 각각 써 보세요. 테이블을 만든 뒤 어느 접두 키를 무효화해야 하는지 설명하면, 단순한 데이터 가져오기를 넘어 캐시 설계를 연습하게 됩니다.

PostgreSQL과 RLS: 인증과 행 단위 허용 조건 나누기

examples/todo-list/nextjs-todo-list/supabase/migrations/20230712094349_init.sql은 todos.user_id를 auth.users에 연결하고 RLS를 켭니다. 조회 정책은 auth.uid() = user_id입니다. ‘로그인했는가’와 ‘이 행의 주인인가’를 다른 질문으로 다루는 기초 예제입니다.

용어 풀이
RLS · 행 수준 보안
테이블에 접근할 수 있는 역할이라도 각 행에 대해 추가 조건을 만족해야 읽거나 바꿀 수 있게 하는 PostgreSQL 기능입니다. GRANT는 테이블 접근 권한, RLS 정책은 행 접근 조건을 담당하므로 둘을 함께 생각해야 합니다.

연습: 사용자 A와 B가 각각 한 행을 가진 표를 만들고, A의 요청에 정책 조건을 대입해 보세요. 일반 역할에서는 정책이 적용되지만 슈퍼유저와 BYPASSRLS 역할은 우회하며, 소유자도 보통 예외입니다. 이는 PostgreSQL 공식 행 보안 문서의 규칙입니다.

분산 시스템: 함수 실행과 실패 처리를 분리하기

docker/volumes/functions/main/index.ts는 VERIFY_JWT가 true이고 OPTIONS가 아닌 요청의 JWT를 검증합니다. 함수별 디렉토리를 찾은 뒤 EdgeRuntime.userWorkers.create()로 작업자를 생성합니다. isValidHybridJWT()는 토큰 헤더의 알고리즘에 따라 HS256과 ES256·RS256의 검증 경로를 나눕니다. 헤더를 읽는 것 자체는 검증이 아니며, 실제 서명 검사는 jose.jwtVerify()에서 수행합니다.

이 함수 라우터의 제한값은 memoryLimitMb = 150, workerTimeoutMs = 400_000, 요청 부재 제한 60_000ms입니다. Compose는 요청 유휴 제한을 150000ms로 설정합니다. 각 값이 제한하는 대상이 다르며, 호스팅 상품 전체에 일괄 적용되는 보장으로 읽으면 안 됩니다.

연습: resolveRuntimeError()의 오류 종류를 ‘시작 실패 / 자원 부족 / 유휴 시간 초과 / 실행 오류’로 분류해 보세요. 재시도는 WorkerAlreadyRetired에만 적용되고 최초 시도 외 최대 3회입니다. 이미 실행된 임의 요청을 모두 재시도하는 정책과 무엇이 다른지 설명하세요.

벡터 검색: 임베딩과 거리 연산을 SQL로 연결하기

examples/ai/edge-functions/supabase/migrations/20240408072601_embeddings.sql은 vector(384) 열과 hnsw 인덱스, vector_ip_ops 연산자 클래스를 정의합니다. 이어지는 examples/ai/edge-functions/supabase/migrations/20240410031515_vector-search.sql의 query_embeddings()는 <#> 연산자로 음의 내적을 계산하고 정렬합니다.

연습: 왜 임계값에 음수가 붙는지, 왜 모델이 만드는 벡터의 차원이 열의 384와 맞아야 하는지 설명해 보세요. 예제 주석의 코사인 유사도와 내적의 결과 동등성은 벡터가 정규화됐다는 전제를 갖습니다. 모든 모델 출력에 무조건 성립하는 설명으로 외우지 마세요.

CI와 테스트: 결과·실행 계획·배포 조합을 따로 확인하기

.github/workflows/pg-meta-tests.yml은 SQL 패키지 변경 시 테스트를 실행합니다. .github/workflows/self-host-tests-smoke.yml은 default, logs, kong, rustfs, kong-rustfs, pgbouncer 조합을 행렬로 검사합니다. 한 가지 기본 구성만 통과해서는 선택 구성을 보장할 수 없다는 판단이 드러납니다.

연습: 함수 하나의 결과 검사, SQL 실행 계획 검사, 여러 서비스의 상태 검사가 각각 잡을 수 있는 오류를 한 개씩 적어 보세요. 비용이 다른 검사를 같은 수준으로 반복하기보다 위험이 있는 경계에 맞추어 배치하는 연습입니다.

기술을 배웠는지 확인하는 가장 좋은 질문은 ‘이 도구가 어떤 상태와 권한의 경계를 책임지는가’를 자기 말로 설명할 수 있는가입니다.

7하드웨어 / 시스템 요구사항

소스 읽기, Studio 개발, 전체 서비스 운영의 비용은 다르다

공식 자체 호스팅 안내의 수치는 apps/docs/content/guides/self-hosting/docker.mdx의 시스템 요구사항 표에서 확인할 수 있습니다. 전체 구성요소를 실행할 때의 기준이며, 특정 앱의 동시 접속자 수나 응답 시간을 보증하는 수치는 아닙니다.

자원공식 최소공식 권장
메모리4 GB8 GB 이상
CPU2코어4코어 이상
디스크40 GB SSD80 GB 이상 SSD

같은 안내는 불필요한 서비스를 제거하면 자원 요구량을 줄일 수 있고, 로그·분석 서비스를 추가하면 더 많은 자원이 필요하다고 설명합니다. 데이터량·인덱스·업로드 파일·백업은 계속 디스크를 차지하므로, 초기 컨테이너가 실행되는 것과 장기 운영에 충분한 것은 다릅니다.

학습 방식별 준비 범위

목적필요한 준비구분할 점
소스와 도식 읽기텍스트 편집기, Git, 검색 도구Node·Docker·GPU 없이 코드의 흐름을 분석할 수 있음
Studio 개발 환경Node >=22.13, pnpm 11.13.1, API 대상화면 서버만 켜도 데이터 서비스가 자동으로 모두 생기지는 않음
전체 자체 호스팅Docker·Compose와 위의 공식 자원 기준호스트와 컨테이너에 할당된 실제 메모리를 함께 확인
AI 예제 확장예제별 Python·모델·추론 환경임베딩 생성 비용과 PostgreSQL의 벡터 저장 비용을 구분

개발 PC의 여유 메모리로는 16 GB 이상을 잡으면 브라우저·편집기·빌드·컨테이너를 함께 다루기 편할 수 있습니다. 이는 공식 최소 사양이 아닌 학습 환경을 위한 여유치 제안입니다. 실제 CI도 Studio 단위 테스트에 약 3 GB, 타입 검사와 일부 빌드에 약 4 GB의 Node 힙 상한을 둡니다. 힙 상한은 전체 프로세스 메모리와 같지 않습니다.

포트와 저장 공간을 읽는 법

자원 계획의 기준
GPU는 기본 Supabase 구성의 필수품이 아니다

기본 Compose에 GPU 장치 요청은 없습니다. 벡터를 데이터베이스에 저장하고 검색하는 일과 신경망 모델로 임베딩을 만드는 일을 분리하면, 어떤 단계에 별도 추론 자원이 필요한지 판단하기 쉽습니다.

시스템 요구사항은 제품 이름 하나에 붙는 숫자가 아니라, 실제로 실행할 서비스와 보관할 데이터의 합으로 결정됩니다.

8직접 해볼 수 있는 실습 과제

읽기 전용 탐색과 수작업 추적으로 설계 원리를 검증하는 다섯 과제

아래 과제는 서버를 설치하거나 저장소 코드를 실행하지 않아도 진행할 수 있습니다. 명령은 저장소 루트를 기준으로 파일을 검색하거나 읽습니다. 완성 기준은 ‘파일을 열었다’가 아니라 입력·출력·권한·실패 조건을 설명할 결과물입니다.

과제 1

요청 하나의 여행 지도 만들기 입문 · 30분

/rest/v1/todos가 어느 서비스로 가는지, Studio의 스키마 조회는 어떤 경로를 지나는지 각각 화살표 다섯 개 안팎으로 그립니다.

완성 기준: 일반 앱 경로에는 PostgREST, 관리 경로에는 Studio 서버와 postgres-meta가 나타나야 합니다. 두 경로의 인증·권한 주체가 같다고 가정하지 않아야 합니다.

# 경로와 호출 위치만 찾아 읽는다.
rg -n 'prefix: /rest/v1/|cluster: rest|prefix_rewrite:' \
  docker/volumes/api/envoy/lds.template.yaml
rg -n 'getSchemas|useSchemasQuery|executeSql' \
  apps/studio/data/database/schemas-query.ts
sed -n '1,110p' \
  'apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts'
과제 2

SQL 식별자와 값을 구분하기 중급 · 40분

ident()와 literal() 구현을 읽고 아래 세 입력의 결과를 손으로 적습니다. 그 뒤 packages/pg-meta/test/pg-format.test.ts의 관련 검증과 비교합니다.

완성 기준: 큰따옴표와 작은따옴표의 역할, 따옴표를 겹쳐 쓰는 이유, 일반 문자열을 safeSql에 바로 넣지 않는 이유를 설명합니다.

입력예상 SQL 조각확인할 이유
ident('user notes')"user notes"공백이 있는 이름의 인용
literal("O'Reilly")'O''Reilly'문자열 내부 작은따옴표 처리
literal(null)NULL문자열 'NULL'과 다른 의미

심화 질문: 테이블 이름을 literal()로 처리하면 왜 원하는 쿼리가 되지 않을까요? 이름과 값을 안전하게 표현하는 방법은 서로 대체할 수 없습니다. 안전성뿐 아니라 SQL 문법상 의미도 맞아야 합니다.

과제 3

두 사용자의 RLS 판정표 작성하기 중급 · 50분

할 일 예제의 SELECT·INSERT·UPDATE 정책을 읽습니다. A와 B의 행이 하나씩 있다고 가정하고, A가 할 수 있는 동작을 표로 만듭니다.

완성 기준: A가 자기 행을 읽는 경우와 B의 행을 읽는 경우를 구분하고, 로그인하지 않은 요청과 관리자 역할의 차이를 적습니다. 테이블 권한과 행 정책이 모두 관련된다는 설명을 포함합니다.

-- 원본 예제를 설명하기 위한 별도의 정책 설계 예
-- 테이블 접근 권한이 있다는 전제에서 정책을 판정한다.
alter table public.todos enable row level security;

create policy own_todos_select on public.todos
for select to authenticated
using ((select auth.uid()) = user_id);

create policy own_todos_update on public.todos
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);

여기서 USING은 수정 전의 행을 고르고, WITH CHECK는 수정 후의 행을 검사합니다. 원본 예제의 UPDATE 정책은 USING만 적습니다. WITH CHECK를 생략하면 USING 조건을 수정 후 행의 검사에도 재사용하므로 곧바로 취약점이라고 단정하면 안 됩니다. 위 예는 두 의도를 명시적으로 보여줍니다.

추가 질문: A가 자기 행의 user_id를 B로 바꾸려 하면 어떤 조건이 막을까요? UPDATE에는 행을 볼 수 있는 SELECT 정책도 함께 고려해야 합니다. 관리자 역할로 확인한 결과는 일반 사용자 정책의 검증을 대신하지 못합니다.

과제 4

캐시 충돌과 무효화 범위를 설계하기 중급 · 40분

databaseKeys를 읽고 A·B 프로젝트의 스키마 목록과 같은 프로젝트의 두 테이블 열 목록을 키 배열로 적습니다. A의 스키마 생성 뒤 갱신할 키를 골라 봅니다.

완성 기준: 프로젝트를 누락한 키가 왜 충돌하는지, 한 자원만 무효화할 때와 프로젝트 접두 키를 무효화할 때의 범위 차이를 설명합니다.

['projects', 'A', 'schemas']
['projects', 'B', 'schemas']
['projects', 'A', 'table-columns', 'public', 'todos']
['projects', 'A', 'table-columns', 'public', 'profiles']
// A의 스키마 조회만 갱신할 때의 기준 키는 무엇일까?
과제 5

성능 회귀를 막는 규칙 제안하기 고급 · 90분

getTableEditorSql()의 CTE별 대상 카탈로그와 ID 필터를 표로 만듭니다. 필터 하나가 사라졌을 때 어떤 테이블 전체 탐색이 늘어날지 예상합니다.

완성 기준: collectSeqScans()가 모으는 정보, allowedSeqScans의 한도, 시간 예산을 함께 설명하고 새 SQL 하나에 적용할 예산 초안을 작성합니다.

// 실행하지 않고 검토하는 테스트 예산 설계 예
{
  allowedSeqScans: {
    pg_constraint: {
      max: 2,
      reason: '역방향 외래 키 탐색에 필요한 구조적 스캔',
    },
  },
  maxExecutionTimeMs: 1000,
}

EXPLAIN ANALYZE는 쿼리를 실제 실행한다는 점도 답안에 포함하세요. 합성 카탈로그의 기본 테이블 수는 packages/pg-meta/test/db/stress-catalog.ts에서 2000입니다. 이 크기에서 만든 예산은 모든 운영 환경의 성능 보증과 다릅니다.

실습의 목표는 큰 서비스를 켜는 데서 끝나지 않고, 요청 한 건의 데이터·권한·캐시·비용을 끝까지 설명하는 것입니다.

9관련 기술 심화 학습 로드맵

한 주에 개념 하나, 소스 경로 하나, 설명 가능한 결과물 하나

HTML·JavaScript의 기본 문법을 알고 있다는 전제로 6주 흐름을 제안합니다. 모든 패키지를 같은 깊이로 공부하기보다, 작은 요청 한 건을 이해한 뒤 그 주변으로 범위를 넓혀 가세요. 각 주의 결과물은 다음 주의 질문을 만드는 재료입니다.

주차배울 개념읽을 소스결과물
1주차관계형 모델, 기본 키·외래 키, CRUD 할 일 예제의 examples/todo-list/nextjs-todo-list/supabase/migrations/20230712094349_init.sql테이블 관계도와 제약 조건 설명
2주차HTTP 경로, 프록시, 상태 검사 docker/docker-compose.yml과 Envoy 설정REST 요청과 관리 요청의 여행 지도
3주차JWT, 역할, GRANT, RLS 할 일 정책과 함수 라우터의 isValidHybridJWT()사용자 A·B·비로그인·관리자의 접근 판정표
4주차React 서버 상태, 캐시 키, 취소·갱신 apps/studio/data/database/schemas-query.ts → apps/studio/data/database/keys.ts → executeSql()조회부터 무효화까지의 상태 흐름도
5주차브랜드 타입, SQL 조립, 런타임 검증 packages/pg-meta/src/pg-format/index.ts와 packages/pg-meta/src/pg-meta-schemas.ts신뢰 경계와 입력 변환 규칙 표
6주차카탈로그, 실행 계획, 성능 회귀 방지 packages/pg-meta/src/sql/studio/table-editor/table.ts → packages/pg-meta/test/db/plan-guard.tsCTE별 필터 지도와 테스트 예산 초안

그다음에는 관심사에 따라 갈라진다

공부의 순서는 제품 기능 목록보다 데이터 한 건의 이동 경로를 기준으로 잡을 때 서로 다른 기술을 연결하기 쉽습니다.

10핵심 키워드 사전

이 글을 다시 읽을 때 막히는 용어를 빠르게 찾기
용어쉬운 설명
PostgreSQL표와 관계, 트랜잭션, 역할을 갖춘 관계형 데이터베이스입니다. Supabase의 데이터 중심축입니다.
스키마테이블과 함수 등을 이름으로 묶는 공간입니다. 폴더와 비슷하지만 데이터베이스 권한과도 연결됩니다.
PostgREST데이터베이스의 테이블·뷰·함수를 HTTP API 자원으로 제공하는 서버입니다.
API 게이트웨이외부 요청을 받아 알맞은 내부 서비스로 보내는 공통 입구입니다. 기본 Compose에서는 Envoy입니다.
JWT서명된 주장들을 담는 토큰 형식입니다. 내용을 읽는 것과 서명·유효 조건을 검증하는 것은 다릅니다.
JWKS서명 검증 등에 쓰는 키를 JSON으로 표현한 묶음입니다. 함수 라우터는 설정된 키 집합을 검증에 사용합니다.
인증 · 인가인증은 요청자의 신원을 확인하는 일, 인가는 그 요청자가 무엇을 할 수 있는지 판단하는 일입니다.
GRANT역할에 테이블 조회 같은 권한을 부여하는 SQL 명령입니다. 행별 정책을 켜는 명령과는 다릅니다.
RLS같은 테이블에서도 사용자나 역할에 따라 접근 가능한 행을 제한하는 데이터베이스 규칙입니다.
publishable key공개 클라이언트가 프로젝트 API에 접근할 때 쓰는 키입니다. 사용자의 행 권한을 대신 판단하지 않습니다.
service_role일반 클라이언트에 노출하면 안 되는 높은 권한의 역할입니다. 일반 사용자의 RLS 동작을 시험하는 용도로 부적절합니다.
카탈로그pg_class·pg_attribute처럼 테이블과 열 자체의 정보를 저장하는 시스템 테이블 집합입니다.
OIDPostgreSQL 내부 객체의 식별자입니다. 편집기 SQL은 요청한 테이블의 OID로 조회 범위를 좁힙니다.
CTEWITH로 이름 붙인 쿼리 부분입니다. 복잡한 SQL을 여러 논리 단계로 나눌 때 사용합니다.
EXPLAIN데이터베이스가 쿼리를 처리할 계획을 보여줍니다. 예상 비용은 실행 시간 단위와 다릅니다.
EXPLAIN ANALYZE쿼리를 실제 수행하며 계획과 측정 정보를 얻습니다. 읽기 전용 설명 명령이라고 생각하면 안 됩니다.
Seq Scan대상을 순서대로 훑는 탐색입니다. 작은 대상에는 합리적이지만 불필요하게 큰 범위면 문제가 됩니다.
브랜드 타입같은 기본 타입에 의미를 구분하는 표식을 더하는 기법입니다. 일반 문자열과 SQL 조각을 구분하는 데 쓰입니다.
캐시 무효화저장해 둔 조회 결과가 오래됐음을 표시하여 필요한 시점에 새로 가져오게 하는 과정입니다.
모노레포여러 앱과 공통 패키지를 하나의 저장소에서 관리하는 방식입니다. 모두 같은 프로세스로 실행된다는 뜻은 아닙니다.
catalog · lockfilecatalog는 공통 의존성 버전 선언, 잠금 파일은 실제로 선택된 의존성 버전과 해석 정보를 담습니다.
연결 풀매 요청마다 데이터베이스 연결을 새로 만드는 부담을 줄이도록 연결을 관리하고 재사용하는 계층입니다.
WebSocket클라이언트와 서버가 연결을 유지하며 양방향으로 메시지를 주고받는 통신 방식입니다.
임베딩문장이나 이미지 등의 특징을 숫자 벡터로 표현한 값입니다. 벡터의 차원과 정규화 조건이 중요합니다.
HNSW벡터를 빠르게 찾기 위한 근사 최근접 이웃 인덱스 방식입니다. 정확도·속도·메모리의 균형을 다룹니다.
자체 호스팅서비스를 직접 관리하는 인프라에 배치하는 방식입니다. 업데이트와 데이터 복구 책임도 함께 맡습니다.

11참고 링크

제품 설명은 공식 문서로, 구현 설명은 고정된 커밋으로 돌아가 확인한다

공식 저장소와 제품 문서

본문에서 따라간 핵심 구현

관련 기술의 원문

현재 상태 (2026-10-23 확인)

항목상태
저장소 · 선정supabase/supabase · GitHub Trending Daily #6
스타 / 포크113,641 / 17,020 · 2026-10-23 GitHub 기준
생성일2019-10-12
주 언어TypeScript · GitHub 기준
최신 릴리스v1.26.08 · 2026-08-07
최근 push2026-10-23
최근 커밋2f548a69 · 2026-10-23
docs(postgis): link to the Security Advisor troubleshooting guide (#51439)
루트 라이선스Apache-2.0 · 외부 서비스와 개별 예제의 라이선스는 별도 확인
추적 파일18,190개 · 해당 커밋의 Git 추적 목록 기준
TypeScript 규모.ts 3,817개 / 480,353줄
.tsx 4,835개 / 602,934줄
합계 1,083,287줄
다른 언어 규모JavaScript 계열 약 69,147줄 · SQL 7,714줄 · Shell 6,463줄
Python 228줄 · Rust 6줄 · Go 소스 0줄
문서·설정 규모Markdown·MDX 297,603줄 · JSON 459,039줄 · YAML 110,843줄
서비스 구성 범위기본 게이트웨이 Envoy · 로그·분석은 선택 구성 · Storage 기본 저장 방식은 파일

줄 수는 추적된 일반 파일을 확장자별로 묶고 물리적 줄을 센 대략적인 규모입니다. 주석·빈 줄·테스트·예제·생성 파일을 포함하며, 마지막 개행이 없는 행도 한 줄로 셌습니다. JavaScript 계열은 .js·.jsx·.mjs·.cjs의 합입니다. 이미지·잠금 파일의 모든 형식을 소스 줄 수에 섞지는 않았습니다. 서비스별 별도 저장소의 코드는 이 수치에 포함되지 않습니다.

쓰기 전에 알아둘 한계
소스에서 읽은 설계와 실제 운영 보장은 구분해야 합니다

이 글의 구현 설명은 커밋 2f548a69와 그 설정 범위에 한정됩니다. 현재 문서의 최신 버전과 당시 잠금 버전은 달라질 수 있습니다. 제품 릴리스 번호, SDK 버전, 각 Docker 이미지 태그도 서로 독립적입니다.

트렌딩 선정과 스타 수는 사용량·품질·그날의 인기 원인을 입증하지 않습니다. Knowledge Base 앱의 존재만으로 순위 상승과의 인과관계를 설명할 수도 없습니다.

자체 호스팅 구성만으로 클라우드의 모든 운영 기능이 재현되지는 않습니다. 성능·보안·복구 능력은 실제 배치 환경과 데이터·정책을 대상으로 검증해야 합니다. 관리자 조회 결과로 일반 사용자 권한을 판단하거나 기본 비밀 값을 그대로 운영에 사용하면 안 됩니다.