TELEPASI

검색하기 전에 통하다

Supabase.com → Self-hosted DB 이전·복원 가이드

강병우
2026.07.17 👁️ 108

Supabase.com(클라우드)에서 백업한 DB 파일을 Self-hosted Supabase(직접 설치)로 복원하는 방법입니다.
통상의 경우 한번만 진행되는 작업인데 방법을 모르면 매우 난감한 상황이 될 수 있습니다.

관련 글

  • [Supabase.com DB 백업·복원] — 클라우드 DB 백업 (pg_dump -F c)
  • [Self-hosted Supabase 일일 백업] — Docker + Cron 일일 백업·복원 (plain SQL + gzip)

클라우드에서 Self-hosted로 옮길 때, 백업 파일 형식PostgreSQL 버전에 따라 복원 방법이 달라집니다. 이 글은 그 절차를 정리합니다.

Plain SQL(평문) 백업이 필요한 경우
Supabase.com(특히 무료 플랜)의 PostgreSQL 버전이 Self-hosted보다 낮을 때가 많습니다. Self-hosted는 설치 시점에 최신 버전을 쓰는 경우가 흔합니다.
이처럼 버전이 맞지 않으면 Custom format(-F c) + pg_restore가 실패할 수 있어, 평문(Plain SQL) 백업으로 우회해야 합니다.
양쪽 PostgreSQL 버전이 같으면 Custom format 그대로 복원(방법 A)해도 됩니다.


개요

항목 Supabase.com (출발) Self-hosted (도착)
백업 도구 pg_dump -F c docker exec ... pg_dump (plain SQL)
파일 형식 Custom format (바이너리) Plain SQL + gzip
확장자 예 example.com_20260207_0238.sql example-backup-20260716.sql.gz
복원 도구 pg_restore gunzip | psql
단계 작업
0 양쪽 PostgreSQL 버전 확인 → 방법 A / B·C 선택
1 Supabase.com에서 백업 (버전에 따라 Custom 또는 Plain)
2 백업 파일을 Self-hosted 서버로 전송
3 Self-hosted DB에 복원 (pg_restore 또는 psql)
4 Studio·앱 연결 정보 변경 및 동작 확인

사전 준비

Supabase.com 측

  • [Supabase.com 백업 가이드]의 스크립트 준비
  • Session pooler 연결 정보 설정 완료
# 클라우드 DB 백업
./supabase_db_backup.sh -prj example.com
# → example.com_20260207_0238.sql (Custom format)

Self-hosted 측

  • Self-hosted Supabase Docker가 실행 중
  • supabase-db 컨테이너 접근 가능
docker ps --filter name=supabase-db

(권장) 복원 전 Self-hosted 안전 백업

Self-hosted DB를 덮어쓰므로, 기존 데이터가 있다면 먼저 백업하세요.

/usr/local/bin/supabase-daily-backup.sh

[Self-hosted 백업 가이드] 참고.


PostgreSQL 버전 확인 (먼저 할 일)

이전 방법을 고르기 전에 Supabase.com과 Self-hosted의 PostgreSQL 버전을 확인하세요.

버전 확인 명령

# Supabase.com (Session pooler 접속 — supabase_db_config.sh 설정값 사용)
export PGPASSWORD="YOUR_DATABASE_PASSWORD"
psql -h "aws-0-ap-northeast-2.pooler.supabase.com" \
     -p 5432 \
     -U "postgres.abcdefghijklmnop" \
     -d postgres \
     -c "SHOW server_version;"
unset PGPASSWORD

# Self-hosted
docker exec supabase-db psql -U postgres -d postgres -c "SHOW server_version;"

Supabase Dashboard → Project Settings → Database 에서도 PostgreSQL 버전을 확인할 수 있습니다.
버전이 다를 경우 백업시도시 에러 발생으로도 확인가능함

버전에 따른 방법 선택

상황 권장 방법 설명
버전이 같음 (예: 둘 다 15.x) 방법 A — Custom format + pg_restore -F c 백업 그대로 복원 가능. 평문 백업 불필요
Supabase.com이 더 낮음 (예: 클라우드 15 → Self-hosted 17) 방법 C — Plain SQL 백업 무료 플랜 + 최신 Self-hosted 조합에서 흔함
Custom format 백업은 이미 받음 + 버전 불일치 방법 B — Plain SQL 변환 기존 파일을 pg_restore -f로 SQL 변환 후 psql

왜 평문(Plain SQL)인가?
Custom format(-F c)은 pg_dump / pg_restore 도구 버전과 밀접하게 연결됩니다. Supabase.com 쪽 PostgreSQL이 낮고 Self-hosted가 최신이면, Custom format 복원 시 pg_restore: error: unsupported version버전 불일치 오류가 날 수 있습니다.
Plain SQL은 PostgreSQL이 SQL 문장을 순서대로 실행하는 방식이라, 메이저 버전이 달라도 (호환 범위 내에서) 이전이 가능한 경우가 많습니다.

선택 흐름

양쪽 PostgreSQL 버전 확인
        │
        ├─ 버전 같음 ──────────► 방법 A (Custom format + pg_restore)
        │
        └─ Supabase.com이 더 낮음 ► 방법 C (Plain SQL 백업) 권장
                                    또는 방법 B (기존 Custom → SQL 변환)

복원 방법

PostgreSQL 버전이 같으면 방법 A를, Supabase.com 버전이 더 낮으면 방법 C(또는 B)를 사용하세요.

방법 A: Docker 컨테이너에서 pg_restore (버전이 같을 때)

양쪽 PostgreSQL 메이저 버전이 같을 때 Custom format 백업을 그대로 복원합니다. 평문 백업은 필요 없습니다.

백업 파일을 컨테이너로 복사한 뒤 pg_restore를 실행합니다.

# 1) 백업 파일을 서버로 업로드 (로컬 PC에서)
scp -P 2222 ./example.com_20260207_0238.sql \
  deploy@example.com:/tmp/

# 2) 컨테이너로 파일 복사
docker cp /tmp/example.com_20260207_0238.sql supabase-db:/tmp/cloud-backup.dump

# 3) 복원 (--clean: 기존 객체 삭제 후 복원)
docker exec supabase-db pg_restore \
  -U postgres \
  -d postgres \
  --clean \
  --if-exists \
  --no-owner \
  --no-acl \
  -F c \
  /tmp/cloud-backup.dump

# 4) 임시 파일 삭제 (선택)
docker exec supabase-db rm -f /tmp/cloud-backup.dump
rm -f /tmp/example.com_20260207_0238.sql

주의: --clean은 기존 테이블·데이터를 삭제합니다. 운영 중이면 앱 트래픽을 잠시 중단하세요.

호스트에서 pg_restore → 컨테이너로 파이프 (파일 복사 없이)

서버에 pg_restore가 설치되어 있고, Docker 네트워크로 DB 포트에 접근할 수 있을 때:

# supabase-db 컨테이너 IP 확인 (예시)
DB_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' supabase-db)

PGPASSWORD=postgres pg_restore \
  -h "$DB_IP" \
  -p 5432 \
  -U postgres \
  -d postgres \
  --clean \
  --if-exists \
  --no-owner \
  --no-acl \
  -F c \
  /tmp/example.com_20260207_0238.sql

Self-hosted Supabase의 postgres 비밀번호는 .env / docker-compose.yml에서 확인하세요. 기본 설치와 다를 수 있습니다.


방법 B: Plain SQL로 변환 후 psql 복원 (버전 불일치 · Custom 파일 보유)

Supabase.com PostgreSQL 버전이 Self-hosted보다 낮아 Custom format 복원이 실패했거나, 이미 -F c 백업만 받아 둔 경우에 사용합니다.

Self-hosted [일일 백업 복원]과 같은 psql 방식으로 복원합니다.

# 1) Custom format → Plain SQL 변환 (서버 또는 로컬 PC)
pg_restore -F c \
  --no-owner \
  --no-acl \
  -f /tmp/cloud-migrate.sql \
  /tmp/example.com_20260207_0238.sql

# 2) Self-hosted DB에 복원
docker exec -i supabase-db psql -U postgres -d postgres < /tmp/cloud-migrate.sql

# 3) 임시 파일 삭제 (선택)
rm -f /tmp/cloud-migrate.sql

변환된 SQL이 크면 gzip으로 압축해 Self-hosted 백업 폴더에 보관할 수 있습니다.

gzip /tmp/cloud-migrate.sql
# → cloud-migrate.sql.gz (이후 gunzip | psql 로 복원 가능)

방법 C: 처음부터 Plain SQL로 백업 (버전 불일치 · 권장)

Supabase.com PostgreSQL 버전이 Self-hosted보다 낮을 때 가장 확실한 방법입니다.
Self-hosted 설치 시 최신 PostgreSQL을 쓰는 경우가 많고, Supabase.com 무료 플랜은 상대적으로 낮은 버전인 경우가 있어 이 방법을 자주 사용합니다.

처음부터 -F c 없이 평문 SQL로 백업하면, 이후 Self-hosted [일일 백업 복원]과 동일한 방식으로 복원할 수 있습니다.

export PGPASSWORD="YOUR_DATABASE_PASSWORD"

pg_dump -h "aws-0-ap-northeast-2.pooler.supabase.com" \
        -p 5432 \
        -U "postgres.abcdefghijklmnop" \
        -d postgres \
        --no-owner \
        --no-acl \
        --clean \
        --if-exists \
        -f example.com_plain_20260207.sql

이후 Self-hosted [일일 백업 복원 절차]와 동일하게:

docker exec -i supabase-db psql -U postgres -d postgres < example.com_plain_20260207.sql
방법 사용 조건 장점 단점
A. pg_restore (컨테이너) 버전 같음 Custom format 그대로, 단계 적음 버전 불일치 시 실패
B. Plain SQL 변환 버전 불일치 + Custom 파일 있음 재백업 불필요 변환 단계 추가
C. Plain SQL 백업 버전 불일치 (권장) 가장 확실, Self-hosted psql 방식과 통일 클라우드에 다시 접속해 백업

전체 이전 흐름 (요약)

[Supabase.com]                    [로컬 PC / 서버]                 [Self-hosted]
     │                                   │                              │
     │  pg_dump -F c                     │                              │
     ├──────────────────────────────────►│  example.com_YYYYMMDD.sql    │
     │                                   │                              │
     │                                   │  scp / docker cp             │
     │                                   ├─────────────────────────────►│
     │                                   │                              │ pg_restore
     │                                   │                              │ (또는 psql)
     │                                   │                              ▼
     │                                   │                         supabase-db

실행 순서 체크리스트 (버전 같을 때 — 방법 A)

# ── Step 0: 버전 확인 ──
# Supabase.com과 Self-hosted 양쪽 SHOW server_version; 결과 비교
# → 같으면 아래 진행, Supabase.com이 더 낮으면 "방법 C" 절차로 전환

# ── Step 1: 클라우드 백업 (로컬 PC) ──
./supabase_db_backup.sh -prj example.com

# ── Step 2: 서버로 전송 ──
scp -P 2222 ./example.com_20260207_0238.sql deploy@example.com:/tmp/

# ── Step 3: (권장) Self-hosted 현재 DB 백업 ──
ssh -p 2222 deploy@example.com "/usr/local/bin/supabase-daily-backup.sh"

# ── Step 4: 복원 (방법 A) ──
ssh -p 2222 deploy@example.com << 'EOF'
docker cp /tmp/example.com_20260207_0238.sql supabase-db:/tmp/cloud-backup.dump
docker exec supabase-db pg_restore \
  -U postgres -d postgres \
  --clean --if-exists --no-owner --no-acl \
  -F c /tmp/cloud-backup.dump
docker exec supabase-db rm -f /tmp/cloud-backup.dump
EOF

# ── Step 5: 확인 ──
ssh -p 2222 deploy@example.com \
  "docker exec supabase-db psql -U postgres -d postgres -c '\dt public.*'"

실행 순서 체크리스트 (버전 불일치 — 방법 C)

# ── Step 0: 버전 확인 ──
# Supabase.com(예: 15.x) < Self-hosted(예: 17.x) → Plain SQL 백업

# ── Step 1: Plain SQL 백업 (로컬 PC) ──
export PGPASSWORD="YOUR_DATABASE_PASSWORD"
pg_dump -h "aws-0-ap-northeast-2.pooler.supabase.com" \
        -p 5432 -U "postgres.abcdefghijklmnop" -d postgres \
        --no-owner --no-acl --clean --if-exists \
        -f example.com_plain_20260207.sql
unset PGPASSWORD

# ── Step 2: 서버로 전송 ──
scp -P 2222 ./example.com_plain_20260207.sql deploy@example.com:/tmp/

# ── Step 3: (권장) Self-hosted 현재 DB 백업 ──
ssh -p 2222 deploy@example.com "/usr/local/bin/supabase-daily-backup.sh"

# ── Step 4: psql 복원 ──
ssh -p 2222 deploy@example.com \
  "docker exec -i supabase-db psql -U postgres -d postgres < /tmp/example.com_plain_20260207.sql"

# ── Step 5: 확인 ──
ssh -p 2222 deploy@example.com \
  "docker exec supabase-db psql -U postgres -d postgres -c '\dt public.*'"

복원 후 확인

DB 데이터

# 테이블 목록
docker exec supabase-db psql -U postgres -d postgres -c "\dt public.*"

# 주요 테이블 row 수
docker exec supabase-db psql -U postgres -d postgres -c "
SELECT
  (SELECT COUNT(*) FROM profiles) AS profiles,
  (SELECT COUNT(*) FROM posts) AS posts;
"

Self-hosted Studio(Dashboard)

브라우저에서 Self-hosted Supabase Studio(http://서버:8000 등)에 접속해 테이블·데이터를 확인합니다.

앱 연결 정보 변경

DB만 이전됩니다. 앱·프론트엔드는 Self-hosted Supabase URL·API Key로 바꿔야 합니다.

항목 Supabase.com Self-hosted
API URL https://xxx.supabase.co https://api.example.com (본인 설정)
anon key Dashboard → API Self-hosted .env / Studio
service_role key Dashboard → API Self-hosted .env

이전되지 않는 것

항목 설명
Storage 파일 DB 백업에 Storage 버킷 파일은 포함되지 않음 — 별도 복사 필요
Auth 설정 OAuth Provider·Redirect URL — Self-hosted Studio에서 재설정
Edge Functions 소스코드를 Self-hosted 환경에 별도 배포
Realtime / Webhook Self-hosted 설정에 맞게 재구성

복원 시 자주 보는 메시지

메시지 의미 조치
WARNING: errors ignored on restore: N 일부 객체 복원 경고 Studio·앱에서 동작 확인. 치명적 ERROR 없으면 진행
ERROR: role "..." does not exist 클라우드 전용 역할 --no-owner 사용. 기능 이상 없으면 무시
ERROR: must be owner of extension ... extension 소유권 Supabase managed extension — 대부분 무시 가능
pg_restore: error: unsupported version pg_dump / pg_restore 버전 불일치 Plain SQL 백업(방법 C) 또는 SQL 변환(방법 B) 사용. 버전 확인 참고
could not open input file 컨테이너 내 경로 오류 docker cp 경로 재확인
FATAL: password authentication failed DB 비밀번호 불일치 Self-hosted .envPOSTGRES_PASSWORD 확인

복원 실패 시 롤백

Step 3에서 만든 Self-hosted 안전 백업으로 되돌립니다.

LATEST=$(ls -t /var/www/example.com/dbBackup/example-backup-*.sql.gz | head -1)
gunzip -c "$LATEST" | docker exec -i supabase-db psql -U postgres -d postgres

[Self-hosted 복원 절차] 참고.


이전 완료 후

Self-hosted에서 [일일 자동 백업] Cron을 등록해 두면, 이후부터는 plain SQL + gzip 방식으로 관리할 수 있습니다.

# Cron 예시
0 0 * * * /usr/local/bin/supabase-daily-backup.sh >> /var/www/example.com/dbBackup/backup.log 2>&1

보안 유의사항

  • 클라우드·Self-hosted 백업 파일 모두 전체 DB 데이터를 포함합니다. 전송·보관 시 접근 권한을 제한하세요.
  • scp·SSH는 포트·계정을 본인 환경에 맞게 변경하세요 (예: -P 2222, deploy@example.com).
  • 복원은 --clean으로 기존 DB를 덮어씁니다. 운영 DB에서는 반드시 사전 백업 후 진행하세요.

주파수 소통방 (0)

로딩 중...