이 글에서 다루는 내용

types.ts는 단순히 DB 스키마를 정의하는 파일이 아니라, 프로젝트 전반에서 사용하는 TypeScript 타입을 한곳에 모아두는 역할을 합니다. 이 글에서는 Supabase와 연동해 타입을 자동 생성하는 방법부터, API 응답·폼·UI 상태·외부 서비스·유틸리티·컴포넌트 Props까지 실전에서 자주 쓰이는 다양한 활용 패턴을 정리합니다.

Supabase 연동으로 types.ts 자동 생성하기

Supabase CLI를 사용하면 DB 스키마를 기반으로 types.ts를 자동으로 생성할 수 있습니다. 수동으로 작성한 타입과 달리 컬럼 추가·삭제 시 명령어 한 번으로 동기화가 가능해 유지보수가 훨씬 편해집니다.

1단계 — Supabase CLI 설치 (최초 1회)

# npm
npm install -g supabase

# macOS (Homebrew)
brew install supabase/tap/supabase

2단계 — Supabase 로그인 (최초 1회)

supabase login

명령 실행 후 브라우저가 열리면 Supabase 계정으로 인증합니다.

3단계 — 프로젝트 Reference ID 확인

Supabase Dashboard에서 아래 경로로 이동해 Reference ID를 복사합니다.

Project Settings → General → Reference ID
예: abcdefghijklmno

4단계 — 타입 생성 명령 실행

npx supabase gen types typescript --project-id <Reference-ID> > src/lib/supabase/types.ts

# 실제 예시
npx supabase gen types typescript --project-id abcdefghijklmno > src/lib/supabase/types.ts

현재 수동으로 작성한 src/lib/supabase/types.ts가 DB 스키마 기반으로 자동 덮어쓰기됩니다.

언제 다시 실행해야 할까?

  • 테이블 컬럼 추가 또는 삭제 시
  • 새 마이그레이션 적용 후
  • Database 타입에서 빨간 줄이 뜰 때

로컬 개발 환경 연결 (선택)

프로젝트 루트에서 아래 명령어를 실행해 프로젝트를 연결해두면 이후에는 --project-id 없이 간단하게 실행할 수 있습니다.

supabase init                              # 최초 1회
supabase link --project-ref <Reference-ID> # 최초 1회

# 이후부터는 아래 명령어만
npx supabase gen types typescript --linked > src/lib/supabase/types.ts

package.json 스크립트 등록 (권장)

팀 작업 시 명령어를 매번 입력하는 번거로움을 줄이려면 스크립트로 등록해두는 것이 좋습니다.

"scripts": {
  "gen:types": "supabase gen types typescript --linked > src/lib/supabase/types.ts"
}

이후에는 npm run gen:types만 실행하면 됩니다.

지금 types.ts를 수동으로 작성해둔 상태라도 빌드·실행에는 문제없습니다. Supabase 프로젝트 생성 후 위 명령어를 한 번 실행해 자동 생성된 파일로 교체하면 깔끔하게 정리됩니다.

types.ts의 다양한 활용 패턴

DB 스키마 타입 외에도 types.ts는 프로젝트 전반의 다양한 타입을 담는 공간으로 활용됩니다.

유니온 타입 / 리터럴 타입

상태나 옵션처럼 값이 정해진 경우 유니온 타입으로 명확하게 표현합니다.

export type Theme = "light" | "dark" | "system"
export type Language = "ko" | "en" | "ja"
export type SortOrder = "asc" | "desc"

공통 API 응답 래퍼

API 응답 형태를 제네릭으로 추상화하면 일관된 처리가 가능합니다.

export interface ApiResponse<T> {
  data: T | null
  error: string | null
  message?: string
}

export interface PaginatedResponse<T> {
  data: T[]
  total: number
  page: number
  limit: number
  hasNext: boolean
}

폼 관련 타입

입력값과 유효성 에러를 타입으로 명확하게 정의합니다.

export interface SubscriptionForm {
  name: string
  amount: number
  cycle: Cycle
  next_payment_date: string
  category: Category
  memo?: string
}

export type FormError<T> = Partial<Record<keyof T, string>>

UI 상태 타입

모달, 토스트 등 UI 상태도 타입으로 정의하면 Props 전달 시 실수를 줄일 수 있습니다.

export interface ModalState {
  isOpen: boolean
  type: "add" | "edit" | "delete" | null
  targetId?: number
}

export interface ToastState {
  message: string
  type: "success" | "error" | "info"
  duration?: number
}

외부 서비스 타입 (Toss Payments 등)

외부 API와 연동할 때 요청·응답 타입을 직접 정의합니다.

export interface TossPaymentConfirmRequest {
  paymentKey: string
  orderId: string
  amount: number
}

export interface TossPaymentConfirmResponse {
  paymentKey: string
  orderId: string
  orderName: string
  method: string
  totalAmount: number
  status: "DONE" | "CANCELED" | "PARTIAL_CANCELED"
  approvedAt: string
}

유틸리티 타입 확장

프로젝트 전반에서 반복적으로 쓰이는 타입 패턴을 미리 정의해 재사용합니다.

export type Nullable<T> = T | null
export type Optional<T> = T | undefined
export type Maybe<T> = T | null | undefined

// 특정 키만 필수로 만들기
export type RequireFields<T, K extends keyof T> = T & Required<Pick<T, K>>

// 타임스탬프 키 제외
export type OmitTimestamps<T> = Omit<T, "created_at" | "updated_at">

컴포넌트 Props 타입

컴포넌트의 Props를 별도 타입으로 정의하면 재사용성과 가독성이 높아집니다.

export interface ButtonProps {
  label: string
  variant: "primary" | "secondary" | "ghost"
  size?: "sm" | "md" | "lg"
  disabled?: boolean
  onClick?: () => void
}

export interface SubscriptionCardProps {
  subscription: Database["public"]["Tables"]["subscriptions"]["Row"]
  onEdit: (id: number) => void
  onDelete: (id: number) => void
}

파일 구조 권장 방식

규모가 커질수록 도메인별로 파일을 분리하는 것이 관리하기 편합니다.

src/
  lib/supabase/types.ts   # DB 스키마 전용 (자동 생성)
  types/
    index.ts              # 공통 타입 모음
    api.ts                # API 요청/응답 타입
    ui.ts                 # UI 상태 타입
    payment.ts            # 결제 관련 타입