개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Supabase Type Generation — 스키마 기반 타입 자동 생성

2025년 4월 26일
SupabaseType GenerationTypeScriptDatabase Typessupabase gen

데이터베이스 스키마와 TypeScript 코드가 어긋나는 순간, 런타임 에러는 예고 없이 찾아온다. Supabase는 supabase gen types typescript 명령 하나로 현재 DB 스키마를 그대로 TypeScript 타입 파일로 변환해 준다. 스키마가 바뀔 때마다 타입을 손으로 맞출 필요가 없어진다.

동작 구조

PostgreSQL Schema
      │
      ▼
supabase gen types typescript
      │
      ▼
 database.types.ts
      │
      ├─► createClient<Database>(...)
      │
      └─► 쿼리 결과에 자동 타입 추론

Supabase CLI가 information_schema를 읽어 테이블·뷰·함수의 컬럼 정보를 추출하고, 이를 TypeScript interface로 변환한다.

information_schema — PostgreSQL이 제공하는 표준 메타데이터 뷰. 테이블 구조, 컬럼 타입, 제약 조건 등을 조회할 수 있다.

타입 파일 생성

Supabase CLI를 설치한 뒤 프로젝트 루트에서 실행한다.

npx supabase gen types typescript \
  --project-id YOUR_PROJECT_ID \
  --schema public \
  > src/types/database.types.ts

--schema 플래그로 여러 스키마를 지정할 수 있다. public,auth처럼 쉼표로 구분하면 된다.

생성된 파일 구조는 다음과 같다.

export type Json = string | number | boolean | null | { [key: string]: Json } | Json[]

export interface Database {
  public: {
    Tables: {
      posts: {
        Row: {
          id: number
          title: string
          created_at: string
        }
        Insert: {
          id?: number
          title: string
          created_at?: string
        }
        Update: {
          id?: number
          title?: string
          created_at?: string
        }
      }
    }
  }
}

Row, Insert, Update 세 가지 변형 타입이 자동으로 생성된다. NOT NULL 컬럼과 DEFAULT 값 유무에 따라 optional 여부가 결정된다.

타입 안전 쿼리 작성

생성된 타입을 createClient에 제네릭으로 넘기면 이후 모든 쿼리에서 자동 추론이 작동한다.

import { createClient } from '@supabase/supabase-js'
import type { Database } from '@/types/database.types'

const supabase = createClient<Database>(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// 반환 타입이 Database['public']['Tables']['posts']['Row'][]로 추론됨
const { data } = await supabase.from('posts').select('*')

존재하지 않는 컬럼을 .select에 넣거나, Insert 타입과 맞지 않는 객체를 .insert에 넘기면 컴파일 단계에서 에러가 발생한다.

자동화

스키마가 변경될 때마다 수동으로 명령을 실행하면 놓치기 쉽다. package.json에 스크립트로 등록해 두는 것이 실용적이다.

{
  "scripts": {
    "gen:types": "supabase gen types typescript --project-id $SUPABASE_PROJECT_ID --schema public > src/types/database.types.ts"
  }
}

CI 파이프라인에서 마이그레이션 적용 후 이 스크립트를 실행하고 생성된 파일을 커밋에 포함시키면, PR 단위로 타입 변경 이력을 추적할 수 있다.

# GitHub Actions 예시
- name: Generate types
  run: npm run gen:types
  env:
    SUPABASE_PROJECT_ID: ${{ secrets.SUPABASE_PROJECT_ID }}

Row vs Insert vs Update 선택 기준

상황사용 타입
SELECT 결과 받기Row
INSERT 데이터 구성Insert
UPDATE 페이로드 구성Update
함수 파라미터 타입 선언Row 또는 Insert

Update 타입은 모든 컬럼이 optional이므로 부분 업데이트에 그대로 사용할 수 있다.

← 이전 글Supabase Migration — 데이터베이스 변경을 코드로 관리하는 방법
다음 글 →Supabase 환경 변수 — API 키를 안전하게 관리하는 방법