새소식

300x250
AI/MCP(2026) vs CLI

개발자를 위한 MCP 추천(5-1) - Supabase MCP 설치 및 사용방법 : 자연어로 PostgreSQL을 다루는 법, AI가 데이터베이스를 직접 설계

  • -
728x90

2026년 3월 · 개발자를 위한 MCP 추천 시리즈

"MCP가 죽었다"말도 나오는데, 그래도 현시점 쓸만한 MCP 10개

2025년에 썼던 개발자용 MCP 시리즈들이, 이제 상당 부분 구버전이 됐다.
생태계가 빠르게 변했고, 새로 등장한 도구들도 많다.
2026년 3월, 다시 한번 실제로 써보고 쓸 만한 것들만 골라 정리해려고 한다.

이 시리즈를 다시 쓰는 이유

지난 2월 말, "MCP는 죽었다, CLI 만세 — Eric Holmes의 도발적 주장"이라는 글을 정리한 적이 있다. Eric Holmes가 주장한 핵심은 간단하다. LLM은 이미 CLI에 능숙하다. 그렇다면 MCP라는 별도의 추상 계층이 굳이 필요한가?

실제로 Claude Code 환경에서 MCP 대신 CLI로 해결되는 경우가 꽤 많다. 디버깅도 쉽고, 별도 프로세스 관리도 없고, 기존 인증도 그대로 쓸 수 있다. 그 글에서 공감하신 분들이 많았다.
그럼에도 불구하고, MCP만이 줄 수 있는 가치가 분명히 존재한다.

 

안녕하세요! 갓대희 입니다.

오늘은 Supabase MCP에 대해 알아보려고 한다.

Supabase가 공식으로 제공하는 MCP 서버다. Claude Code 같은 AI 에이전트에서 자연어로 DB 스키마를 잡고, SQL도 돌리고, 프로젝트 관리까지 할 수 있다.

목차

  1. Supabase MCP란?
  2. 설치 방법 (Claude Code / settings.json / Claude Desktop)
  3. 주요 기능(Tools) 소개
  4. 실전 활용 예시
  5. Supabase CLI vs Supabase MCP 비교
  6. 주의사항 및 트러블슈팅
  7. 개발자 커뮤니티 반응
  8. 결론

1. Supabase MCP란?

Supabase MCP는 Supabase 공식 팀이 개발한 MCP 서버이다.

오픈소스 저장소는 supabase-community/supabase-mcp이며, 호스팅 엔드포인트는 https://mcp.supabase.com/mcp이다.

보통 Supabase 작업은 대시보드 SQL Editor에서 직접 쿼리를 실행하거나, supabase CLI로 마이그레이션을 관리하는 방식으로 이루어진다. Supabase MCP를 쓰면 Claude Code 대화창에서 "users 테이블에 created_at 컬럼 추가해줘"라고 하면 마이그레이션까지 자동으로 적용해준다.

Supabase MCP가 특별한 이유
그냥 SQL을 실행하는 것만이 아니라, 스키마 변경은 apply_migration으로, 데이터 조회는 execute_sql로 구분해준다. DDL(Data Definition Language)과 DML(Data Manipulation Language)이 분리되어 있어서, 실수로 스키마를 날려먹을 위험이 줄어든다. read_only 모드도 있어서 조회만 허용하고 변경은 아예 막아버릴 수도 있다.

 

2. 설치 방법

ex) 공식 문서 링크를 주거나 https://supabase.com/docs/guides/getting-started/mcp 그냥 자연어로 figma mcp 설치해줘.

( 반대로 내 블로그 링크를 주고  해당 mcp 설치 해줘 라고 진행해도 진행 된다. )

 

방법 1: Claude Code CLI 설치 (권장)

Claude Code가 설치된 상태에서 프로젝트 디렉토리에서 아래 명령어를 실행한다.

# Step 1: MCP 서버 등록
claude mcp add --transport http supabase https://mcp.supabase.com/mcp
→ Added HTTP MCP server supabase with URL: https://mcp.supabase.com/mcp to local config
주의: 등록만으로는 바로 사용할 수 없다
MCP 서버를 등록한 직후에는 아직 OAuth 인증이 완료되지 않았기 때문에 연결 실패(Failed to connect) 상태다. Claude Code를 반드시 재시작해야 인증 플로우가 트리거된다.
# Step 2: 현재 세션 종료 후 재시작
/exit # 또는 Ctrl+D
claude

# Step 3: 연결 상태 확인
claude mcp list
supabase: https://mcp.supabase.com/mcp (HTTP) - ✗ Failed to connect
# ↑ 처음에는 이렇게 나온다. 정상이다.
OAuth 수동 인증
Claude Code 재시작 후 /mcp를 입력하면 다음과 같이 Supabase MCP 상태가 표시된다.
Supabase MCP Server

Status: failed
Auth: not authenticated
URL: https://mcp.supabase.com/mcp

  1. Authenticate
  2. Reconnect
  3. Disable
ex) /mcp

1. Authenticate
를 선택하면 브라우저가 열리면서 Supabase 권한 승인 페이지가 나타난다.

"Authorize API access for Claude Code (supabase)" 화면에서 다음을 확인한다:
  • Permissions 목록 — Postgres 설정 Read/Write, Edge Functions, 프로젝트 관리 등 MCP가 요청하는 권한 범위를 확인
  • Organization to grant API access to — 연결할 조직을 선택 (여러 조직이 있으면 드롭다운에서 선택)

 

"Authorize Claude Code (supabase)" 버튼을 클릭하면 인증이 완료된다.
인증 후 터미널에 Authentication successful, but server still requires authentication 메시지가 나올 수 있다. Claude Code를 한 번 더 재시작하면 정상 연결된다.

인증 완료 후 확인:
claude mcp list
supabase: https://mcp.supabase.com/mcp (HTTP) - ✓ Connected
OAuth가 안 될 때 — PAT 방식으로 전환
브라우저 팝업이 뜨지 않거나, OAuth 인증이 반복적으로 실패하는 경우 PAT(Personal Access Token) 방식으로 전환한다. CI/CD 환경이나 헤드리스 서버에서도 PAT를 사용해야 한다.
# 기존 MCP 제거 후 PAT 방식으로 재등록
claude mcp remove supabase
claude mcp add --transport http supabase "https://mcp.supabase.com/mcp" \
  --header "Authorization: Bearer YOUR_SUPABASE_PAT"
PAT 발급: Supabase 대시보드 → 우측 상단 프로필 → Account → Access Tokens → Generate New Token

 

방법 2: settings.json 직접 설정 (기본)

Claude Code 설정 파일에 직접 추가하는 방법이다.

// .claude/settings.json (프로젝트별) 또는 ~/.claude.json (글로벌)
{
  "mcpServers": {
    "supabase": {
      "type": "http",
      "url": "https://mcp.supabase.com/mcp"
    }
  }
}

특정 프로젝트로 범위를 좁히려면 URL에 project_ref 파라미터를 추가한다. 프로젝트 참조 ID는 Supabase 대시보드 → Project Settings → General에서 확인할 수 있다.

// 특정 프로젝트로 범위 제한
{
  "mcpServers": {
    "supabase": {
      "type": "http",
      "url": "https://mcp.supabase.com/mcp?project_ref=abcdefghijklmnop"
    }
  }
}

 

방법 3: Personal Access Token (PAT) 방식 (OAuth 실패 시 / CI 환경)

OAuth 인증이 반복적으로 실패하거나, CI/CD 환경처럼 브라우저가 없는 환경에서는 PAT를 사용한다. 실제로 OAuth가 잘 트리거되지 않는 경우가 종종 있으므로, PAT 방식이 가장 확실한 연결 방법이다.

PAT 발급 방법: Supabase 대시보드 → 우측 상단 프로필 아이콘 → Account → Access Tokens → Generate New Token

# CLI로 PAT 방식 등록 (OAuth 대신 사용할 때)

# 기존 OAuth 방식 MCP가 있다면 먼저 제거
claude mcp remove supabase

# PAT + 특정 프로젝트로 재등록
claude mcp add --transport http supabase \
  "https://mcp.supabase.com/mcp?project_ref=YOUR_PROJECT_REF" \
  --header "Authorization: Bearer YOUR_SUPABASE_PAT"

settings.json에 직접 작성하는 경우:

// PAT + 특정 프로젝트 범위 설정
{
  "mcpServers": {
    "supabase": {
      "type": "http",
      "url": "https://mcp.supabase.com/mcp?project_ref=${SUPABASE_PROJECT_REF}",
      "headers": {
        "Authorization": "Bearer ${SUPABASE_ACCESS_TOKEN}"
      }
    }
  }
}

 

방법 4: Claude Desktop 설정

Claude Desktop(GUI 앱)에서 Settings → Connectors → Add custom connector로 추가한다.

  • Name: Supabase
  • URL: https://mcp.supabase.com/mcp
  • Authentication: OAuth (브라우저 자동 처리)

 

Read-only 모드 설정

데이터 조회만 허용하고 스키마 변경은 막고 싶을 때 사용한다. 프로덕션 DB 연결 시 강력히 권장한다.

{
  "mcpServers": {
    "supabase": {
      "type": "http",
      "url": "https://mcp.supabase.com/mcp?project_ref=xxx&read_only=true"
    }
  }
}

 

3. 주요 기능(Tools) 소개

Supabase MCP는 8개 그룹, 30개 넘는 tool이 있다. 그룹 단위로 켜고 끌 수 있는데, Storage 그룹만 기본 꺼져 있고 나머지는 다 켜져 있다. (출처: Supabase 공식 MCP 문서)

실제로 써보면 제일 많이 쓰게 되는 Tool 3개
  1. execute_sql — SELECT·INSERT·UPDATE·DELETE 등 DML 작업은 거의 다 여기로 온다. "어떤 데이터 보여줘"라고 하면 결국 이 tool이 호출된다.
  2. apply_migration — 테이블 생성·수정·인덱스 추가 같은 DDL 변경을 마이그레이션 이력으로 남기면서 적용해준다. 스키마 작업할 때 핵심.
  3. list_tables — 현재 스키마가 어떻게 생겼는지 파악하는 출발점. Claude가 SQL을 제대로 짜려면 먼저 이걸 호출해서 테이블 구조를 봐야 한다.

 

데이터베이스 (Database)

Tool 이름 설명
list_tables 지정한 스키마의 테이블 목록을 조회한다.
list_extensions 데이터베이스에 설치된 PostgreSQL 확장 목록을 조회한다.
list_migrations 적용된 마이그레이션 이력을 조회한다.
apply_migration DDL SQL(CREATE TABLE, ALTER TABLE 등 스키마 변경)을 마이그레이션으로 적용한다.
execute_sql 일반 SQL 쿼리(SELECT, INSERT, UPDATE, DELETE)를 실행한다. 스키마를 변경하지 않는 작업에 사용한다.
apply_migration vs execute_sql 구분
  • apply_migration: CREATE TABLE, ALTER TABLE, CREATE INDEX 등 DDL — 마이그레이션 이력에 기록됨
  • execute_sql: SELECT, INSERT, UPDATE, DELETE 등 DML — 이력에 기록되지 않음
read_only 모드에서 비활성화되는 tool 목록: apply_migration, create_project, pause_project, restore_project, deploy_edge_function, create_branch, delete_branch, merge_branch, reset_branch, rebase_branch, update_storage_config. execute_sql은 read-only Postgres 사용자로 실행되어 SELECT만 허용된다.
RLS(Row Level Security) 주의사항
Supabase MCP의 execute_sqlRLS가 적용되지 않는 관리자 수준 권한으로 실행된다. 테이블에 RLS를 아무리 꼼꼼하게 걸어놔도 MCP로 쿼리하면 모든 행이 다 보인다. Supabase 공식 문서는 프로덕션 DB에 MCP를 연결하지 말 것을 1순위로 권고한다. 부득이하게 실제 데이터에 접근해야 하는 경우에만 read_only=true를 차선책으로 사용해야 한다. 개발이나 분석용 관리자 접근에는 편하지만, 사용자별 데이터 격리가 필요하다면 Supabase 클라이언트를 직접 쓰는 게 안전하다.
execute_sql 토큰 먹는 하마 주의
MCP의 execute_sql 결과는 전부 LLM의 context window에 들어간다. 수천 행짜리 결과를 몇 번 반복하면 토큰이 순식간에 날아가서 대화가 엉뚱해지거나 context 한도에 걸린다. 실제로 써보면서 느낀 건데, 이게 생각보다 빨리 찬다.

이렇게 쓰는 게 좋다:
  1. LIMIT 꼭 붙이기: LIMIT 없이 쿼리 날리면 전체 행이 context에 들어간다. SELECT * FROM users LIMIT 20 이런 식으로 습관 들이자.
  2. 집계 쿼리 쓰기: 전체를 끌어오지 말고 COUNT, AVG, GROUP BY 같은 집계 함수로 요약본만 받자. "사용자 몇 명이야?"는 Claude가 알아서 SELECT count(*)를 쓰긴 하는데, 대량 데이터일 때는 직접 명시해주는 게 안전하다.
  3. 대량 작업은 CLI + psql로: 수만 건 이상 export하거나 bulk 처리해야 하면, MCP로 하지 말고 직접 psql이나 supabase db dump를 쓰는 게 낫다.

 

디버깅 (Debugging)

Tool 이름 설명
get_logs 프로젝트 로그를 가져온다. API, 데이터베이스, Edge Functions 로그 등을 조회할 수 있다.
get_advisors 데이터베이스 성능 및 보안 개선 권고사항을 가져온다.

 

개발 도우미 (Development)

Tool 이름 설명
get_project_url 프로젝트의 API URL을 가져온다.
get_publishable_keys 프론트엔드에서 사용하는 anon key 등 공개 키를 가져온다.
generate_typescript_types 현재 데이터베이스 스키마를 기반으로 TypeScript 타입을 자동 생성한다.

 

Edge Functions

Tool 이름 설명
list_edge_functions 배포된 Edge Functions 목록을 조회한다.
get_edge_function 특정 Edge Function의 상세 정보를 가져온다.
deploy_edge_function Edge Function을 배포한다.

 

계정 및 프로젝트 관리

Tool 이름 설명
list_projects / get_project Supabase 프로젝트 목록 및 상세 정보를 조회한다.
create_project 새 Supabase 프로젝트를 생성한다.
pause_project / restore_project 프로젝트를 일시 중지하거나 복원한다.
list_organizations / get_organization Supabase 조직 목록 및 정보를 조회한다.
get_cost 프로젝트 또는 조직의 현재 비용 정보를 조회한다.
confirm_cost 비용이 발생하는 작업(프로젝트 생성 등) 전에 예상 비용을 확인하고 승인한다.
search_docs Supabase 공식 문서를 검색한다.

 

브랜치 관리 (Branching — 실험적)

Supabase의 Preview Branch 기능과 연동된다. 아직 실험적 기능이므로 프로덕션 환경에서는 주의해서 사용한다.

create_branch, list_branches, delete_branch, merge_branch, reset_branch, rebase_branch

 

스토리지 (Storage — 기본 비활성화)

Storage 그룹은 기본적으로 비활성화되어 있다. 필요한 경우 명시적으로 활성화해야 한다.

list_storage_buckets, get_storage_config, update_storage_config

 

4. 실전 활용 예시

시나리오 1: 자연어로 DB 스키마 설계

새 프로젝트 시작할 때 ERD 그리기도 전에 Claude Code에서 바로 스키마를 잡아보는 흐름이다.

사용자: 블로그 서비스를 만들려고 해. users, posts, comments, tags 테이블이 필요하고, posts와 tags는 다대다 관계야. RLS도 기본으로 설정해줘. Supabase에 스키마 만들어줘.

[list_tables 호출 → 현재 테이블 없음 확인]

 

Claude: 현재 public 스키마에 테이블이 없습니다. 요구사항에 맞게 5개 테이블(users, posts, comments, tags, post_tags)과 RLS 정책을 포함한 마이그레이션을 생성하겠습니다.

[apply_migration 호출 — name: "create_blog_schema"]

 

Claude: 마이그레이션이 완료되었습니다. 생성된 구조:
users — id(UUID), email(TEXT UNIQUE), created_at
posts — id, user_id(FK→users), title, content, published, created_at
comments — id, post_id(FK→posts), user_id(FK→users), body, created_at
tags — id, name(UNIQUE)
post_tags — post_id + tag_id (다대다 조인 테이블)
모든 테이블에 RLS가 활성화되었고, 인증된 사용자만 자기 데이터를 CRUD할 수 있는 기본 정책이 적용되었습니다.

# Claude Code 내부 동작 (tool 호출)

list_tables(schemas: ["public"])
→ 현재 테이블 없음 확인

apply_migration(name: "create_blog_schema", query: `
CREATE TABLE users (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE posts (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  title TEXT NOT NULL,
  content TEXT,
  published BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
-- ... comments, tags, post_tags 테이블 및 RLS 정책
`)
→ 마이그레이션 완료: 5개 테이블, RLS 정책 설정됨
참고: 실제 프로젝트에서 list_tables를 호출하면?
이미 테이블이 있는 프로젝트에서 list_tables를 호출하면 다음과 같이 기존 스키마를 파악할 수 있다. 아래는 실제 Supabase 프로젝트(서울 리전, PostgreSQL 17)에서 조회한 결과다.
list_tables(schemas: ["public"], verbose: false)
→ 20개 테이블 발견:
  goddaehee_blog_posts (RLS ✓) | goddaehee_documents (4,717행)
  intraday_top50_members (40,400행) | alert_events (2,826행)
  dart_financial_snapshots (26,168행) | intraday_bars_5m (15,815행)
  trade_universe_snapshots (28행) | trading_risk_policy (1행)
  ... 외 12개 테이블
Claude는 이 정보를 보고 테이블 간 FK 관계, 컬럼 타입 같은 걸 파악한 다음 SQL을 짠다.

 

시나리오 2: 자연어로 SQL 쿼리 실행 및 결과 분석

SQL을 직접 안 짜고 자연어로 데이터를 뽑아보는 시나리오다. 아래는 실제로 내 Supabase 프로젝트(주식 트레이딩 데이터, 40,000건 넘음)에서 돌려본 결과다.

사용자: 거래량 급증률이 가장 높은 종목 Top 5를 보여줘. 종목명, 현재가, 등락률, 급등률을 포함해줘.

[execute_sql 호출 — SELECT ... FROM intraday_top50_members ORDER BY surge_rate DESC LIMIT 5]

 

Claude: 조회 결과입니다:

| rank | stock_name | current_price | change_rate | surge_rate |
|------|------------|---------------|-------------|------------|
| 1    | 흥아해운   | 3,035         | +29.98%     | 66.90     |
| 2    | 대한해운   | 2,515         | +14.32%     | 875.74    |
| 3    | 남선알미늄 | 1,723         | +14.41%     | 34.67     |
| 4    | 빛과전자   | 1,678         | +18.50%     | 195.42    |
| 5    | 센서뷰     | 4,562         | +24.64%     | 77.52     |

 

Claude: 대한해운이 surge_rate 875.74로 압도적 1위입니다. 해운 섹터(흥아해운, 대한해운)가 상위권을 차지하고 있어 해운 업종에 테마 수급이 몰린 것으로 보입니다. 흥아해운은 등락률 +29.98%로 가장 높은 가격 변동을 보이고 있습니다.

ex) 실제 수행 결과

실제 내 프로젝트에서 돌려본 결과
위 예시는 진짜 내 Supabase 프로젝트에서 execute_sql로 뽑은 거다. intraday_top50_members(40,360건), alert_events(2,867건), dart_financial_snapshots(26,168건) 등 20개 테이블이 있는 프로젝트인데, "거래량 급증 종목 보여줘" 한 줄로 SQL이 만들어져서 바로 결과가 나왔다.
# 실제 tool 호출
execute_sql(query: `
SELECT
  rank_no,
  stock_name,
  current_price,
  change_rate,
  surge_rate
FROM intraday_top50_members
ORDER BY created_at DESC, surge_rate DESC
LIMIT 5
`)
→ 5개 행 반환
실제 테이블 기반 추가 예제 SQL
위 프로젝트의 실제 테이블 구조를 기반으로, 자주 쓰게 되는 분석 쿼리 예시를 정리해봤다. 자연어로 요청하면 Claude가 아래와 비슷한 SQL을 알아서 짜준다.
-- 최근 7일간 급등 Top50 일별 진입 건수
SELECT date_trunc('day', created_at) AS day,
       count(*) AS entry_count
FROM public.intraday_top50_members
WHERE created_at >= now() - interval '7 days'
GROUP BY day ORDER BY day;
-- 종목별 알림 발생 빈도 TOP 10
SELECT stock_code, stock_name,
       count(*) AS alert_count,
       count(DISTINCT event_type) AS event_types
FROM public.alert_events
GROUP BY stock_code, stock_name
ORDER BY alert_count DESC LIMIT 10;
참고: 실제 테이블 목록 — intraday_top50_members(40,360건, 급등 Top50 실시간 진입), alert_events(2,867건, 주식 알림 이벤트), dart_financial_snapshots(26,168건, DART 재무제표), intraday_bars_5m(15,815건, 5분봉 OHLCV), goddaehee_documents(4,717건, RAG 문서 청크 + 벡터 임베딩)

 

시나리오 3: RLS 정책 설정 대화

기존 테이블에 RLS를 거는 과정이다. 보안 설정은 한 번 실수하면 골치 아프니까, AI가 정책을 먼저 제안하고 내가 확인한 다음 적용하는 식으로 진행하는 게 안전하다.

사용자: posts 테이블에 RLS를 설정해줘. 누구나 읽을 수 있지만 작성/수정/삭제는 본인만 가능하게.

Claude: 다음 RLS 정책을 적용하겠습니다:
1. SELECT — 모든 사용자 허용 (익명 포함)
2. INSERT — 인증된 사용자만, user_id = auth.uid()
3. UPDATE — user_id = auth.uid()인 행만
4. DELETE — user_id = auth.uid()인 행만

이 정책을 적용할까요?

사용자: 네, 적용해줘.

[apply_migration 호출 — name: "add_posts_rls_policies"]

Claude: 마이그레이션이 완료되었습니다. posts 테이블에 4개의 RLS 정책이 적용되었습니다. 확인을 위해 현재 정책을 조회해보겠습니다.

[execute_sql 호출 — pg_policies 테이블 조회]

# apply_migration으로 적용된 SQL
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- 누구나 읽기 가능
CREATE POLICY "posts_select_all" ON posts
  FOR SELECT USING (true);

-- 본인만 생성
CREATE POLICY "posts_insert_own" ON posts
  FOR INSERT WITH CHECK (auth.uid() = user_id);

-- 본인만 수정
CREATE POLICY "posts_update_own" ON posts
  FOR UPDATE USING (auth.uid() = user_id);

-- 본인만 삭제
CREATE POLICY "posts_delete_own" ON posts
  FOR DELETE USING (auth.uid() = user_id);

 

시나리오 4: read_only 모드 vs 전체 모드 비교

프로덕션 DB에 read_only=true로 붙었을 때 어떻게 다른지 보여주는 예시.

read_only 모드 (프로덕션 권장)

사용자: users 테이블에 phone 컬럼 추가해줘.

Claude: 현재 read_only 모드로 연결되어 있어서 스키마 변경이 불가능합니다. apply_migration 도구가 비활성화되어 있습니다. 스키마를 변경하려면 개발 환경의 MCP 연결(read_only 파라미터 제거)을 사용하거나 Supabase CLI로 마이그레이션을 적용해야 합니다.


사용자: 그러면 intraday_top50_members 테이블에 데이터가 몇 건 있는지 확인해줘.

[execute_sql 호출 — SELECT count(*) FROM intraday_top50_members → 정상 실행]

Claude: intraday_top50_members 테이블에 현재 40,400건의 레코드가 있습니다.

read_only 모드에서 비활성화되는 tool 목록
apply_migration, create_project, pause_project, restore_project, deploy_edge_function, create_branch, delete_branch, merge_branch, reset_branch, rebase_branch. execute_sql은 read-only Postgres 사용자로 실행되어 SELECT만 허용된다.

 

시나리오 5: Edge Function 생성 및 배포

Edge Function을 Claude Code 대화 안에서 만들고 바로 배포까지 하는 시나리오.

사용자: 이메일 주소를 받아서 welcome 이메일을 보내는 Edge Function을 만들어서 배포해줘.

 

Claude: send-welcome-email Edge Function을 생성하겠습니다. Resend API를 사용하는 기본 구현으로 만들겠습니다.

[deploy_edge_function 호출 — name: "send-welcome-email", body: Deno 함수 코드]

 

Claude: 배포가 완료되었습니다. 엔드포인트:

POST https://abcdefgh.supabase.co/functions/v1/send-welcome-email

# 테스트 호출 예시
curl -X POST https://abcdefgh.supabase.co/functions/v1/send-welcome-email \
  -H "Authorization: Bearer <anon_key>" \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com"}'

 

Claude: RESEND_API_KEY 환경 변수를 Supabase 대시보드 → Edge Functions → send-welcome-email → Secrets에서 설정해야 실제 이메일이 발송됩니다.

 

시나리오 6: TypeScript 타입 자동 생성 후 코드에 반영

스키마 바꾸고 나서 TypeScript 타입도 같이 맞춰주는 흐름이다.

사용자: posts 테이블에 view_count integer 컬럼 추가하고, TypeScript 타입 다시 생성해서 src/types/database.ts 파일 업데이트해줘.

[apply_migration 호출 — name: "add_view_count_to_posts"]

 

Claude: view_count 컬럼이 추가되었습니다. 이제 TypeScript 타입을 생성하겠습니다.

[generate_typescript_types 호출 → 타입 정의 생성]

[src/types/database.ts 파일에 생성된 타입 저장]

 

Claude: 완료! posts 테이블 타입에 view_count: number | null이 추가되었습니다. 기존 코드에서 view_count를 사용하는 부분이 있으면 타입 체크가 자동으로 적용됩니다.

Claude Code가 apply_migration으로 컬럼 추가하고, generate_typescript_types로 타입 뽑고, 파일까지 써주는 걸 알아서 해준다.

팁: get_advisors 써보기
get_advisors를 가끔 호출해보면 인덱스 빠진 거, RLS 안 건 테이블, 비효율적인 쿼리 같은 걸 Supabase가 알려준다. 그냥 "내 DB에 문제 있는지 확인해줘"라고 물어보면 된다.

 

5. Supabase CLI vs Supabase MCP 비교

Supabase CLI와 MCP는 서로 보완 관계다. 둘 다 쓰는 게 편하다.

 

Supabase CLI 주요 명령어

로컬 개발 환경 셋업, 마이그레이션 버전 관리, CI/CD 연동 같은 건 MCP보다 CLI가 맞다.

# 설치
npm install -g supabase

# 로컬 Supabase 환경
supabase init # 프로젝트 초기화 (supabase/ 폴더 생성)
supabase start # 로컬 Supabase 스택 시작 (Docker 필요)
supabase stop # 로컬 스택 중지
supabase status # 로컬 서비스 상태 확인

# 마이그레이션 관리 (버전 관리 가능한 방식)
supabase migration new <name> # 새 마이그레이션 파일 생성
supabase db push # 원격 DB에 마이그레이션 적용
supabase db pull # 원격 스키마를 로컬로 가져오기
supabase db reset # 로컬 DB 초기화 후 마이그레이션 재적용

# TypeScript 타입 생성
supabase gen types --lang typescript --local # 로컬 DB 기반 타입 생성
supabase gen types --lang typescript --project-id <ref> # 원격 DB 기반 타입 생성

# Edge Functions
supabase functions new <name> # Edge Function 생성
supabase functions deploy <name> # Edge Function 배포
supabase functions serve # 로컬에서 Edge Function 실행

# 스키마 관리 & 품질 검사 (CLI 전용)
supabase db diff # 로컬과 원격 스키마 차이 감지 → 마이그레이션 자동 생성
supabase migration squash # 여러 마이그레이션을 하나로 합치기 (이력 정리)
supabase db lint # Postgres 린트 — 스키마 안티패턴 검출 (splinter 기반)
supabase test db # pgTAP 기반 데이터베이스 단위 테스트 실행
supabase inspect db # 성능 분석 — 13개 서브커맨드 (bloat, index-usage 등)

# 원격 프로젝트 연결
supabase link --project-ref <ref> # 원격 프로젝트와 연결
로컬 MCP 연결 (CLI랑 MCP 같이 쓰기)
supabase start로 로컬 스택을 띄우면 http://localhost:54321/mcp로 로컬 DB에 MCP 연결이 된다. 개발할 때는 로컬 MCP로, 스테이징/프로덕션 배포는 CLI로 나누면 안전하다.

supabase start 후 로컬 스택 서비스 포트 목록

서비스 기본 포트 설명
API Gateway 54321 Kong 기반 API 게이트웨이 (REST/GraphQL 엔드포인트)
PostgreSQL 54322 로컬 Postgres DB (psql -h localhost -p 54322로 직접 접속 가능)
Studio 54323 Supabase Studio 웹 UI (브라우저에서 DB 관리)
Mailpit 54324 이메일 테스트 서버 (Auth 이메일 확인용)
Auth 54321/auth GoTrue 기반 인증 서비스 (API Gateway 경유)
Storage 54321/storage 파일 스토리지 서비스 (API Gateway 경유)
Realtime 54321/realtime WebSocket 기반 실시간 구독 서비스 (API Gateway 경유)

포트는 supabase/config.toml에서 변경할 수 있다. supabase status 명령어로 실행 중인 서비스와 포트를 한눈에 확인 가능하다.

항목 Supabase CLI Supabase MCP
사용 방식 터미널 명령어 직접 입력 AI 에이전트가 자동 호출
로컬 개발 supabase start로 로컬 Supabase 실행 로컬 CLI 사용 시 localhost:54321/mcp 연결
마이그레이션 supabase migration new 후 파일 직접 작성 apply_migration으로 AI가 자동 생성 및 적용
TypeScript 타입 supabase gen types --lang typescript 명령어 generate_typescript_types로 자동 생성 후 파일에 저장
SQL 실행 psql 또는 대시보드 SQL Editor execute_sql로 자연어 → SQL 자동 변환 실행
CI/CD 통합 GitHub Actions 등 파이프라인에 직접 통합 PAT 방식으로 CI 환경에서도 사용 가능
적합한 상황 로컬 환경 관리, CI/CD 자동화 스키마 설계, 데이터 분석, 개발 중 빠른 DB 작업
권장 조합: 로컬 환경 셋업이랑 CI/CD는 CLI로, 스키마 설계랑 데이터 분석은 MCP로 나눠 쓰면 된다. 실제로 이렇게 나눠 쓰니까 작업 흐름이 꽤 깔끔했다.

 

MCP 전용 vs CLI 전용 — 배타적 기능 비교

MCP와 CLI는 겹치는 부분도 있는데, 각자만 되는 게 있다. 이걸 알아야 어떤 상황에서 뭘 쓸지 판단이 빨라진다.

MCP 전용 기능

  • get_advisors — DB 성능/보안 어드바이저
  • search_docs — Supabase 공식 문서 검색
  • get_logs — API/DB/Edge Function 로그 조회
  • list_storage_buckets — 스토리지 버킷 관리
  • read_only 모드 — URL 파라미터로 쓰기 차단
  • Claude Desktop 통합 — GUI 앱에서 직접 사용
  • 자연어 인터페이스 — SQL 몰라도 DB 조회 가능

CLI 전용 기능

  • supabase db diff — 스키마 차이 감지/마이그레이션 생성
  • supabase db lint — Postgres 린트 (splinter 기반)
  • supabase test db — pgTAP 데이터베이스 단위 테스트
  • supabase migration squash — 마이그레이션 합치기
  • supabase functions serve — Edge Function 로컬 실행
  • supabase inspect db — 성능 분석 (13개 서브커맨드)
  • CI/CD 통합 — GitHub Actions 등 파이프라인 직접 연동
  • 오프라인 개발supabase start로 네트워크 없이 개발

 

MCP + CLI 조합 추천 워크플로우

실전에서는 MCP와 CLI를 같이 쓸 때가 제일 편하다. 내가 실제로 써보면서 괜찮았던 조합 3가지를 정리했다.

조합 1: MCP로 테이블 설계/쿼리 → CLI로 타입 생성

# 1. MCP: Claude Code에서 자연어로 스키마 설계 → apply_migration 자동 적용
# 2. CLI: 변경된 스키마 기반으로 TypeScript 타입 생성
supabase gen types --lang typescript --project-id <ref> > src/types/database.ts

조합 2: CLI로 로컬 개발 → MCP로 원격 점검

# 1. CLI: 로컬 Supabase 스택 실행
supabase start
# 2. MCP: 원격 프로젝트에 연결하여 성능/보안 점검
# "내 DB 성능 개선 사항 확인해줘" → get_advisors 호출
# "최근 에러 로그 보여줘" → get_logs 호출

조합 3: MCP로 데이터 분석 → CLI로 자동화

# 1. MCP: 자연어로 데이터 분석 → execute_sql로 결과 확인
# 2. CLI: 분석 결과 기반 스키마 변경 자동화
supabase db diff --use-migra -f optimize_indexes # 스키마 차이 감지
supabase migration squash # 마이그레이션 정리
supabase db push # 원격 적용

 

6. 주의사항 및 트러블슈팅

자주 발생하는 문제

문제 1: "Failed to connect" — MCP 등록 후 연결 실패
가장 흔한 문제다. claude mcp add로 등록하면 config에 추가만 되고, OAuth 인증은 아직 진행되지 않은 상태이기 때문이다. claude mcp list를 실행하면 supabase: ... - ✗ Failed to connect가 나온다.
해결:
  1. Claude Code를 완전히 종료한다 (/exit 또는 Ctrl+D)
  2. 터미널에서 claude를 다시 실행한다
  3. 재시작 후 Supabase MCP tool을 호출하면 (예: "내 테이블 목록 보여줘") 브라우저가 열리면서 OAuth 인증이 시작된다
  4. 인증 완료 후 claude mcp list에서 ✓ Connected 확인

그래도 안 되면: PAT 방식으로 전환한다. Supabase 대시보드에서 Access Token을 발급받아 --header "Authorization: Bearer YOUR_PAT"로 재등록한다. (2. 설치 방법 참조)
문제 2: apply_migration 실패 — "permission denied"
read_only 모드로 설정했거나, PAT에 충분한 권한이 없는 경우다.
해결: URL에서 read_only=true 파라미터가 없는지 확인한다. PAT를 사용한다면 Supabase 대시보드에서 해당 토큰의 권한을 확인한다.
문제 3: execute_sql로 DDL을 실행했는데 마이그레이션 이력에 없음
execute_sql은 마이그레이션 이력에 기록되지 않는다. 스키마 변경은 반드시 apply_migration을 써야 한다.
해결: AI에게 스키마 변경 시 apply_migration을 쓰도록 명시적으로 지시한다. 예: "스키마 변경은 반드시 apply_migration으로 해줘."
문제 4: MCP 연결은 되는데 원하는 프로젝트가 안 보임
여러 Supabase 프로젝트가 있을 때 올바른 프로젝트를 찾지 못하는 경우다.
해결: URL에 project_ref 파라미터를 추가한다. 프로젝트 참조 ID는 Supabase 대시보드 → Project Settings → General에서 확인한다.

Supabase CLI 사용 시 트러블슈팅

Supabase MCP와 함께 CLI를 쓸 때 실제로 겪은 오류들이다. CLI 설치/사용 과정에서 빠지기 쉬운 함정들을 정리했다.

문제 5: supabase login — non-TTY 환경에서 로그인 실패
Claude Code 내부 Bash에서 supabase login을 실행하면 다음 에러가 발생한다:
Cannot use automatic login flow inside non-TTY environments.
Please provide --token flag or set the SUPABASE_ACCESS_TOKEN environment variable.
원인: Claude Code의 Bash 환경은 interactive TTY가 아니라서, 브라우저 기반 로그인 플로우가 트리거되지 않는다.
해결: 별도 터미널 창을 열어서 supabase login을 실행한다. 또는 --token 플래그나 SUPABASE_ACCESS_TOKEN 환경 변수를 사용한다.
문제 6: supabase inspect db--project-ref 플래그 미지원
supabase inspect db table-stats --project-ref xxx를 실행하면 다음 에러가 나온다:
unknown flag: --project-ref
원인: inspect 명령어는 linked 프로젝트에서만 동작한다. --project-ref 플래그를 직접 받지 않는다.
해결: 먼저 디렉토리를 만들고 link한 다음 inspect를 실행한다:
mkdir -p ~/my-project && cd ~/my-project
supabase init
supabase link --project-ref <project-ref>
supabase inspect db table-stats
문제 7: supabase inspect db table-sizes deprecated
table-sizes를 실행하면 다음 경고가 나온다:
Command "table-sizes" is deprecated, use "table-stats" instead.
해결: table-sizes 대신 table-stats를 사용한다. 기존 스크립트나 문서에서 table-sizes로 되어 있으면 table-stats로 바꿔주자.
문제 8: psql 미설치 (macOS)
CLI의 일부 기능이나 직접 DB 접속 시 psql이 필요한데, macOS에 기본 설치되어 있지 않다:
command not found: psql
해결:
brew install libpq
export PATH="/opt/homebrew/opt/libpq/bin:$PATH"

# 영구 적용:
echo 'export PATH="/opt/homebrew/opt/libpq/bin:$PATH"' >> ~/.zshrc
libpq는 PostgreSQL 클라이언트 라이브러리로, psql을 포함한다. 전체 PostgreSQL 서버를 설치할 필요 없이 클라이언트만 설치하는 가벼운 방법이다.

 

보안 주의사항

보안 관련 꼭 지킬 것
  • 개발/테스트용으로 쓰자: 프로덕션 DB에 붙여야 한다면 read_only=true는 필수다.
  • PAT 하드코딩 금지: Personal Access Token은 코드에 직접 넣지 말고, 환경 변수로 관리하자. .gitignore도 잊지 말고.
  • Service Role Key 주의: get_publishable_keys로 anon key는 가져올 수 있는데, service_role key는 AI한테 직접 붙여넣지 말자.
  • Human Confirmation 켜두기: 스키마 변경 전에 Claude Code의 Human Confirmation이 켜져 있는지 확인하자. 실수로 테이블 날리면 진짜 멘탈 나간다.

 

7. 개발자 커뮤니티 반응 (2026년 초 기준)

2026년 초 기준으로 Supabase MCP에 대한 반응은 대체로 괜찮은 편인데, 프로덕션에서 쓸 때는 조심해야 한다는 목소리도 꽤 있다.

긍정적 반응
  • 스키마 설계 초기에 "ERD 없이 자연어만으로 테이블을 완성했다"는 반응이 많다. Next.js·React 쪽 풀스택 개발자들 사이에서 "백엔드 셋업이 한결 가벼워졌다"는 이야기가 꽤 나온다.
  • RLS 정책 같은 SQL 문법이 좀 까다로운 작업에서 "AI가 먼저 제안하고, 확인 후 적용하니까 실수가 줄었다"는 반응도 있다. "보안 설정을 같이 검토하는 느낌"이라는 표현이 종종 보인다.
  • TypeScript 타입 생성(generate_typescript_types)이랑 스키마 변경을 한 대화 안에서 이어서 할 수 있다는 점도 반응이 좋다.
실무 한계 지적
  • HTTP Remote MCP라서 execute_sql 결과가 전부 context window에 들어간다. 수천 행짜리 쿼리를 몇 번 돌리면 토큰이 금방 바닥난다. LIMIT을 꼭 붙이거나 집계 쿼리로 요약해서 받아야 한다.
  • 서비스 롤 권한으로 실행되다 보니 RLS를 우회한다. 이걸 모르고 프로덕션 DB에 full-access로 붙였다가 데이터가 노출된 사례가 커뮤니티에 올라온 적 있다. read_only=true를 꼭 붙이라고 하는 이유가 이거다.
  • apply_migration이 이력은 남기는데, Git에 자동으로 커밋해주진 않는다. 팀으로 작업할 때 마이그레이션 파일 동기화 문제가 생길 수 있어서, CLI랑 같이 쓰는 게 좋다.

(참고: Supabase 공식 MCP 문서, supabase-mcp GitHub Issues, Supabase 공식 블로그 — Supabase MCP Server)

 

8. 결론

실제로 써보면, Supabase MCP는 초기 스키마 잡을 때 제일 빛난다. 자연어로 요구사항 말하면 테이블 구조, FK 관계, RLS 정책까지 한 방에 잡아준다. 이 부분은 솔직히 좀 놀라웠다.

데이터 분석 쪽도 쓸만하다. SQL 안 쓰는 기획자가 "지난달에 가입한 사용자 중 게시글 3개 이상 쓴 사람 몇 명이야?" 이런 식으로 물어보면 Claude Code가 SQL 짜서 바로 결과를 뽑아준다.

Supabase MCP 요약 정리
  • 공식 Remote MCP: https://mcp.supabase.com/mcp
  • 설치: claude mcp add --transport http supabase https://mcp.supabase.com/mcp
  • 인증: OAuth 자동 처리 (PAT 선택 사항)
  • 스키마 변경: apply_migration / 데이터 조회: execute_sql
  • 특정 프로젝트: URL에 ?project_ref=xxx 파라미터 추가
  • 읽기 전용 모드: ?read_only=true (프로덕션 DB 연결 시 권장)
  • 8개 그룹, 30개 이상의 tool 제공 (Storage 그룹은 기본 비활성화)
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.

💡 AI 관련 질문이 있나요? 눌러보세요!