Supabase CLI 사용법: 개발자 완벽 가이드 (2026년)

Ashley Innocent

Ashley Innocent

24 March 2026

Supabase CLI 사용법: 개발자 완벽 가이드 (2026년)

요약 (TL;DR)

Supabase CLI는 Docker를 사용하여 PostgreSQL, Auth, Storage, Edge Functions 등 전체 Supabase 스택을 로컬 머신에서 실행합니다. brew install supabase/tap/supabase로 설치하고, supabase initsupabase start를 실행하여 로컬 환경을 설정한 다음, supabase db pushsupabase functions deploy를 사용하여 프로덕션 환경에 배포하세요. 클라우드에 접속하지 않고도 Supabase 백엔드를 구축하고 테스트하는 가장 빠른 방법입니다.

소개

개발자들이 로컬 테스트를 건너뛰기 때문에 백엔드 버그의 73%가 프로덕션 환경에서 발견됩니다. Supabase CLI를 사용하면 더 이상 이런 변명은 통하지 않습니다. 5분 안에 머신에서 완벽한 프로덕션과 동일한 환경을 얻을 수 있습니다.

여기 진짜 문제가 있습니다: 대부분의 개발자는 프로덕션 환경에서 직접 테스트하거나(위험) 클라우드와 완벽하게 일치하지 않는 로컬 환경을 구성하는 데 몇 시간을 보냅니다(좌절). Supabase CLI는 이 두 가지 문제를 모두 해결합니다. 프로덕션을 정확히 미러링하는 Docker 기반 로컬 스택을 제공하여 로컬에서 작동하는 것이 프로덕션에서도 작동하게 합니다.

💡
Supabase 위에 API를 구축한다면, 엔드포인트를 설계, 테스트 및 문서화할 도구가 필요할 것입니다. Apidog는 Supabase의 REST 및 GraphQL API에 직접 연결되어 로컬에서 백엔드를 구축하는 동안 테스트할 수 있도록 해줍니다.
button

Apidog로 Supabase API를 무료로 테스트하세요

이 가이드가 끝나면 다음을 할 수 있게 됩니다:

CLI 없이 로컬 Supabase 개발이 어려운 이유

CLI 없이 Supabase 앱을 구축하려고 시도해 본 적이 있다면, 그 고통을 알 것입니다. 다음은 끊임없이 발생하는 세 가지 시나리오입니다.

"운영 환경에서 테스트" 함정. Supabase 대시보드에서 직접 스키마를 변경합니다. 잘 작동합니다. 프론트엔드를 푸시합니다. 3일 후, 동료가 레포를 풀하면 데이터베이스에 새 컬럼이 없어서 앱이 고장 납니다.

환경 불일치. 로컬 PostgreSQL 인스턴스를 설정하고, 수동으로 Supabase 스키마를 다시 생성하며, Row Level Security 정책이 로컬에서 다르게 작동하는 이유를 디버깅하는 데 두 시간을 보냅니다. 정책이 다르게 작동하는 것이 아니라, 정책 하나를 놓친 것입니다.

"내 컴퓨터에서는 잘 되는데" 문제. Edge Function은 Supabase 대시보드 편집기에서는 작동하지만, 실제 환경 변수 대신 하드코딩된 값으로 테스트했기 때문에 프로덕션 환경에서는 실패합니다.

이것들은 특수한 경우가 아닙니다. 스키마 드리프트(로컬 및 원격 데이터베이스의 동기화 불일치)는 Supabase를 사용하는 팀에서 가장 많이 보고되는 문제입니다. CLI는 이 세 가지 문제를 모두 해결합니다:

Supabase CLI 작동 방식

로컬 스택

supabase start를 실행하면 CLI는 다음 서비스가 포함된 Docker Compose 스택을 시작합니다:

서비스 포트 목적
PostgreSQL 54322 데이터베이스
PostgREST 54321 자동 생성 REST API
GoTrue 54321/auth 인증 서비스
Realtime 54321/realtime WebSocket 구독
Storage 54321/storage 파일 스토리지
Studio 54323 시각적 대시보드
Inbucket 54324 이메일 테스트 (모든 이메일을 로컬에서 포착)
Edge Runtime 54321/functions Deno 기반 함수 러너

이것은 Supabase Cloud에서 실행되는 것과 동일한 스택입니다. 여러분의 로컬 머신에서요.

설치

macOS:

brew install supabase/tap/supabase

Windows (Scoop):

scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase

Linux / npm:

npm install -g supabase

설치 확인:

supabase --version
# supabase 1.x.x
supabase start

프로젝트 설정

mkdir my-project && cd my-project
supabase init

이렇게 하면 다음이 생성됩니다:

supabase/
├── config.toml       # 포트, 인증 설정, 스토리지 구성
├── seed.sql          # 데이터베이스 재설정 시마다 로드되는 개발 데이터
└── migrations/       # 스키마 버전 기록

로컬 스택 시작하기

supabase start

첫 실행 시 약 1GB의 Docker 이미지를 다운로드합니다. 그 후에는 시작하는 데 약 10초가 걸립니다.

API URL: http://localhost:54321
DB URL:  postgresql://postgres:postgres@localhost:54322/postgres
Studio:  http://localhost:54323
anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

anon key.env.local 파일에 복사하세요. 프론트엔드에 필요할 것입니다.

마이그레이션을 통한 데이터베이스 관리

마이그레이션은 CLI 워크플로우의 핵심입니다. 모든 스키마 변경은 Git에서 추적되는 버전 관리된 SQL 파일이 됩니다. 더 이상 "누가 언제 데이터베이스를 변경했는지"에 대해 고민할 필요가 없습니다.

첫 마이그레이션 생성

supabase migration new create_posts_table
# 생성됨: supabase/migrations/20260324120000_create_posts_table.sql

파일 편집:

-- RLS와 함께 posts 테이블 생성
CREATE TABLE posts (
  id          UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id     UUID REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
  title       TEXT NOT NULL,
  content     TEXT,
  published   BOOLEAN DEFAULT false,
  created_at  TIMESTAMPTZ DEFAULT NOW(),
  updated_at  TIMESTAMPTZ DEFAULT NOW()
);

-- Row Level Security 활성화
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- 누구나 발행된 게시물을 읽을 수 있음
CREATE POLICY "Anyone can read published posts"
  ON posts FOR SELECT
  USING (published = true);

-- 사용자는 자신의 게시물을 관리
CREATE POLICY "Users manage own posts"
  ON posts FOR ALL
  USING (auth.uid() = user_id);

-- 변경 시마다 updated_at 자동 업데이트
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER posts_updated_at
  BEFORE UPDATE ON posts
  FOR EACH ROW EXECUTE FUNCTION update_updated_at();

적용하기:

supabase migration up

TypeScript 타입 생성

스키마 변경 후에는 항상 타입을 다시 생성하세요:

supabase gen types typescript --local > src/types/database.ts

프론트엔드가 완전한 타입 안전성을 확보합니다:

import { Database } from '@/types/database'

type Post = Database['public']['Tables']['posts']['Row']
type NewPost = Database['public']['Tables']['posts']['Insert']

// 이제 에디터가 런타임 전에 타입 에러를 잡아냅니다
const createPost = async (post: NewPost) => {
  const { data, error } = await supabase
    .from('posts')
    .insert(post)
    .select()
    .single()
  return data
}

개발 데이터 시딩

supabase/seed.sql 편집:

-- 테스트 사용자 (로컬 개발용으로 인증 우회)
INSERT INTO auth.users (id, email) VALUES
  ('00000000-0000-0000-0000-000000000001', 'alice@example.com'),
  ('00000000-0000-0000-0000-000000000002', 'bob@example.com');

-- 테스트 게시물
INSERT INTO posts (user_id, title, content, published) VALUES
  ('00000000-0000-0000-0000-000000000001', 'Supabase 시작하기', '내가 배운 것은...', true),
  ('00000000-0000-0000-0000-000000000002', '초안: API 설계 패턴', '작업 중...', false);

언제든지 재설정 및 시드 재적용:

supabase db reset

이렇게 하면 모든 것이 초기화되고, 모든 마이그레이션이 다시 실행되며, 시드 데이터가 로드됩니다. 매일 아침 새롭게 시작하기 위해 실행하세요.

Apidog로 Supabase API 테스트하기

로컬 Supabase가 실행되면 http://localhost:54321에 완벽하게 작동하는 REST API가 생성됩니다. Supabase는 PostgREST를 통해 모든 테이블에 대한 엔드포인트를 자동 생성합니다. curl로 이러한 엔드포인트를 수동으로 테스트하는 것은 특히 다른 사용자 토큰으로 RLS 정책을 테스트해야 할 때 빠르게 번거로워집니다.

Apidog는 로컬 Supabase 인스턴스에 직접 연결됩니다. 다음을 수행할 수 있습니다:

로컬 Supabase로 Apidog 설정하기:

  1. Apidog에서 새 프로젝트 생성
  2. 기본 URL 설정: http://localhost:54321
  3. 환경 변수 추가: anon_key = 여러분의-로컬-익명-키
  4. 인증 헤더 추가: Bearer {{anon_key}}

posts 엔드포인트 테스트하기:

GET http://localhost:54321/rest/v1/posts?published=eq.true
Authorization: Bearer {{anon_key}}
apikey: {{anon_key}}

이를 요청으로 저장하고, 응답에 최소 하나의 게시물이 포함되어 있다는 어설션을 추가한 다음, RLS 정책을 변경할 때마다 실행하세요. 프로덕션에 도달하기 전에 깨진 정책을 잡아낼 수 있습니다.

Apidog로 Supabase API 테스트 시작하기

Edge Functions: 로컬에서 빌드 및 테스트

Edge Functions는 사용자에게 가까운 엣지에서 Deno로 실행됩니다. 웹훅, 백그라운드 작업, 서버 측 로직이 필요한 API 엔드포인트에 완벽합니다.

함수 생성

supabase functions new send-welcome-email

이렇게 하면 supabase/functions/send-welcome-email/index.ts가 생성됩니다:

import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

serve(async (req) => {
  const { user_id } = await req.json()

  // 서비스 역할은 RLS를 우회합니다 - 주의해서 사용하세요
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
  )

  const { data: profile } = await supabase
    .from('profiles')
    .select('email, full_name')
    .eq('id', user_id)
    .single()

  // 여기에 이메일 발송 로직을 추가하세요
  console.log(`Sending welcome email to ${profile?.email}`)

  return new Response(
    JSON.stringify({ success: true }),
    { headers: { 'Content-Type': 'application/json' } }
  )
})

핫 리로드로 로컬 테스트

supabase functions serve

함수 서버는 파일 변경 사항을 감지하고 자동으로 다시 로드합니다. 테스트해 보세요:

curl -X POST http://localhost:54321/functions/v1/send-welcome-email \
  -H "Authorization: Bearer YOUR_ANON_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "00000000-0000-0000-0000-000000000001"}'

운영 환경 배포

# 단일 함수 배포
supabase functions deploy send-welcome-email

# 모든 함수 배포
supabase functions deploy

고급 기술 및 검증된 접근 방식

시크릿 관리

함수에 API 키를 하드코딩하지 마세요. 시크릿을 사용하세요:

# 운영 시크릿 설정
supabase secrets set RESEND_API_KEY=re_xxx STRIPE_KEY=sk_live_xxx

# 모든 시크릿 나열
supabase secrets list

# 시크릿 제거
supabase secrets unset STRIPE_KEY

함수에서 접근:

const resendKey = Deno.env.get('RESEND_API_KEY')
// 절대로 이렇게 하지 마세요: const resendKey = 're_xxx'

데이터베이스 브랜칭

큰 스키마 변경 작업을 하고 있나요? 격리된 브랜치를 생성하세요:

supabase branches create feature-payments
supabase branches switch feature-payments

# 변경사항을 만들고 테스트한 다음 병합
supabase branches merge feature-payments

이렇게 하면 실험하는 동안 주요 개발 데이터베이스를 깨끗하게 유지할 수 있습니다.

피해야 할 일반적인 실수

성능 팁

# 메모리를 절약하기 위해 필요 없는 서비스는 건너뛰세요
supabase start --exclude-studio --exclude-inbucket

# 어떤 리소스가 사용 중인지 확인
docker stats

대안 및 비교

기능 Supabase CLI Firebase CLI PlanetScale CLI
로컬 데이터베이스 완전한 PostgreSQL 에뮬레이터만 클라우드만
마이그레이션 Git의 SQL 파일 기본 지원 없음 브랜칭
Edge Functions Deno 런타임 클라우드 함수 포함되지 않음
로컬 인증 완전한 GoTrue 에뮬레이터 포함되지 않음
오픈 소스 완전한 오픈 소스 독점 독점
타입 생성 내장 수동 수동

Firebase의 로컬 에뮬레이터는 빠른 프로토타이핑에는 좋지만, 실제 PostgreSQL 인스턴스를 제공하지 않습니다. PlanetScale의 브랜칭 모델은 스키마 변경에는 탁월하지만, 항상 클라우드에 의존해야 합니다. Supabase CLI는 완전한 오픈 소스, PostgreSQL 네이티브 로컬 개발 경험을 원하는 팀에게 가장 적합합니다.

실제 사용 사례

멀티 테넌트 데이터를 사용하는 SaaS 애플리케이션. 핀테크 스타트업은 세 가지 환경(개발, 스테이징, 운영)에 걸쳐 47개의 마이그레이션을 관리합니다. RLS 정책은 어떤 코드도 운영 환경에 도달하기 전에 다른 사용자 역할로 로컬에서 테스트됩니다. 결과: 6개월 동안 스키마 관련 운영 환경 사고가 전혀 없었습니다.

전자상거래 주문 처리. 전자상거래 팀은 Stripe 웹훅 처리에 Edge Functions를 사용합니다. 그들은 실제 Stripe 테스트 이벤트를 사용하여 supabase functions serve로 웹훅 페이로드를 로컬에서 테스트합니다. 배포 시간이 2시간에서 15분으로 단축되었습니다.

모바일 앱 백엔드. React Native 팀은 모든 마이그레이션 후 TypeScript 타입을 생성하고 이를 내부 npm 패키지로 공유합니다. 프론트엔드와 백엔드는 자동으로 동기화됩니다. 더 이상 Slack에서 "이 엔드포인트가 어떤 필드를 반환하나요?"라는 질문을 하지 않습니다.

마무리

이제 다음을 할 수 있습니다:

이 워크플로우는 즉시 효과를 발휘합니다. 팀은 더 빠르게 배포하고, 버그를 더 일찍 잡아내며, 다시는 스키마 드리프트에 시달리지 않을 것입니다.

다음 단계:

  1. 설치: brew install supabase/tap/supabase
  2. 프로젝트에서 supabase init 실행
  3. 첫 마이그레이션 생성
  4. 로컬 엔드포인트를 테스트하기 위해 Apidog 설정
  5. 자신 있게 운영 환경에 배포

Apidog로 Supabase API를 무료로 테스트하세요

button

자주 묻는 질문 (FAQ)

Supabase CLI를 사용하려면 Docker가 필요합니까?네. supabase start를 실행하기 전에 Docker Desktop이 실행 중이어야 합니다. CLI는 Docker Compose를 사용하여 전체 스택을 로컬에서 실행합니다. Docker가 실행되고 있지 않으면 "Cannot connect to Docker daemon" 오류가 발생합니다.

로컬 데이터베이스를 운영 환경과 동기화하려면 어떻게 해야 합니까?supabase db pull을 사용하여 원격 스키마에서 마이그레이션을 생성한 다음, supabase db push를 사용하여 로컬 마이그레이션을 운영 환경에 적용합니다. 풀 후 로컬에서 supabase db reset을 실행하여 환경이 일치하는지 확인하세요.

Supabase Cloud 계정 없이 Supabase CLI를 사용할 수 있습니까?네. 클라우드 계정 없이도 개발을 위해 CLI를 완전히 로컬에서 사용할 수 있습니다. 운영 환경에 배포할 준비가 되었을 때만 supabase loginsupabase link가 필요합니다.

팀에서 마이그레이션 충돌을 어떻게 처리해야 합니까?새로운 마이그레이션을 생성하기 전에 최신 Git 변경 사항을 풀하고 supabase db reset을 실행하세요. 설명적인 마이그레이션 이름을 사용하고, 호환성을 깨는 스키마 변경을 할 때는 팀원들과 소통하세요.

supabase db pushsupabase migration up의 차이점은 무엇입니까?supabase migration up은 보류 중인 마이그레이션을 로컬 데이터베이스에 적용합니다. supabase db push는 원격(운영) 프로젝트에 적용합니다. 항상 로컬에서 먼저 테스트하세요.

기존 프로젝트와 Supabase CLI를 사용할 수 있습니까?네. supabase link --project-ref YOUR_PROJECT_ID를 실행하여 기존 프로젝트에 연결한 다음, supabase db pull을 사용하여 현재 원격 스키마에서 마이그레이션을 생성할 수 있습니다.

RLS 정책을 로컬에서 어떻게 테스트합니까?http://localhost:54323의 Supabase Studio를 사용하여 사용자 역할을 전환하거나, 다른 JWT 토큰으로 API를 통해 테스트하세요. Apidog는 이를 쉽게 만듭니다. 다른 사용자 토큰으로 여러 환경을 생성하고 다른 사용자로 동일한 요청을 실행할 수 있습니다.

Supabase CLI는 무료입니까?네. CLI는 무료이며 오픈 소스입니다. 로컬 개발에는 비용이 들지 않습니다. Supabase Cloud 리소스는 운영 환경에 배포할 때만 비용을 지불합니다.

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요