화. 8월 12th, 2025

G: 안녕하세요, 개발자 여러분! 🚀 클라우드 서비스의 편리함은 알지만, 때로는 데이터 주권, 비용 최적화, 혹은 순수한 호기심 때문에 직접 서비스를 구축하고 싶다는 생각이 들 때가 있습니다. 오늘 우리가 다룰 주제는 바로 “Supabase”를 내 서버에 직접 구축하는 방법입니다.

Supabase는 Firebase의 오픈소스 대안으로 불리며, 강력한 PostgreSQL 데이터베이스를 기반으로 인증(Auth), 실시간 구독(Realtime), 스토리지(Storage), 엣지 함수(Edge Functions) 등 다양한 백엔드 기능을 제공합니다. 이 글에서는 Docker를 이용해 Supabase의 핵심 컴포넌트들을 배포하고, 사용자 정의 API 도메인에 연결하는 실질적인 노하우를 공유해 드릴게요.

시작해 볼까요? ✨


💡 왜 Supabase를 직접 구축해야 할까요?

Supabase Cloud는 훌륭한 서비스지만, 직접 구축했을 때 얻을 수 있는 몇 가지 이점이 있습니다.

  • 데이터 주권 및 제어권 강화: 🛡️ 내 서버에 데이터가 있으니 데이터가 어디에 저장되는지, 누가 접근할 수 있는지 완벽하게 제어할 수 있습니다. 민감한 데이터를 다루는 경우 특히 중요하죠.
  • 비용 최적화 가능성: 💰 소규모 프로젝트나 특정 워크로드에서는 클라우드 서비스보다 직접 구축하는 것이 장기적으로 더 저렴할 수 있습니다. 물론 서버 비용, 유지보수 비용 등을 고려해야 하지만요!
  • 맞춤형 구성 및 확장성: ⚙️ 특정 서비스만 필요하거나, 기존 인프라와 통합해야 할 때 유연하게 구성할 수 있습니다.
  • 학습 및 이해 증진: 🧠 Supabase가 내부적으로 어떻게 동작하는지 깊이 이해할 수 있는 좋은 기회입니다.

물론, 직접 구축은 초기 설정 및 유지보수 노력이 필요하다는 점을 명심해야 합니다. 단순하고 빠르게 시작하고 싶다면 Supabase Cloud를 사용하는 것이 훨씬 편리할 수 있습니다.


🛠️ 사전 준비물

본격적인 시작에 앞서, 다음과 같은 준비물들이 필요합니다.

  1. 리눅스 서버 (Ubuntu 20.04+ 권장): 💻 최소 4GB RAM, 2코어 CPU 이상을 권장합니다.
    • AWS EC2, Google Cloud Compute Engine, DigitalOcean Droplet, Vultr 등 어떤 클라우드 서버도 좋습니다.
  2. Docker 및 Docker Compose: 🐳 서버에 Docker와 Docker Compose가 설치되어 있어야 합니다.
    • 설치 방법: sudo apt update && sudo apt install docker.io docker-compose -y (Ubuntu 기준)
  3. 도메인 이름: 🌐 yourdomain.com과 같은 자신만의 도메인이 필요합니다.
  4. DNS 관리 접근 권한: 도메인의 DNS 레코드를 수정할 수 있어야 합니다. (예: Cloudflare, Gabia, Namecheap 등)
  5. SSH 접속 도구 및 기본 리눅스/CLI 지식: 🧑‍💻 서버에 접속하고 명령어를 입력할 수 있어야 합니다.
  6. 방화벽 설정 지식: 🔒 필요한 포트(80, 443, 5432 등)를 열고 닫을 수 있어야 합니다.

🧩 Supabase 핵심 컴포넌트 이해하기

Supabase는 여러 오픈소스 프로젝트들의 조합으로 이루어져 있습니다. 직접 구축할 때 어떤 컴포넌트들이 실행되는지 대략적으로 이해하면 좋습니다.

  • PostgreSQL: 🐘 핵심 데이터베이스입니다. 모든 데이터와 Supabase의 내부 데이터가 저장됩니다.
  • PostgREST: 📊 PostgreSQL 데이터베이스를 RESTful API로 즉시 노출시켜주는 도구입니다. 테이블에 변경이 생기면 자동으로 API도 업데이트됩니다.
  • GoTrue: 👤 인증(Authentication) 서버입니다. 사용자 등록, 로그인, 비밀번호 재설정 등 인증 관련 기능을 담당합니다. JWT(JSON Web Token)를 생성하고 관리합니다.
  • Realtime: 🚀 PostgreSQL 데이터베이스의 변경 사항을 실시간으로 클라이언트에 스트리밍하는 서버입니다.
  • Storage: 📦 파일 스토리지 서비스입니다. S3 호환 스토리지를 사용하여 파일을 업로드하고 관리할 수 있습니다.
  • Kong: 🕸️ API 게이트웨이로, 모든 Supabase 서비스의 프록시 역할을 하며 라우팅, 인증, 로깅 등을 처리합니다.
  • Inbucket: 📧 개발 환경에서 이메일 테스트를 위한 SMTP 서버입니다. (실제 운영에서는 SendGrid, Mailgun 등 사용)

이 컴포넌트들은 docker-compose.yml 파일에 정의되어 함께 실행됩니다.


🐳 Supabase Docker Compose 설정하기

이제 본격적으로 Docker Compose 파일을 설정해 봅시다.

1. Supabase 저장소 클론 및 이동

먼저, Supabase의 공식 Docker 저장소를 클론합니다.

git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker

2. 환경 변수 파일(.env) 설정

docker 디렉토리 내에 .env.example 파일이 있습니다. 이 파일을 cp .env.example .env 명령으로 .env 파일로 복사한 후, 내용을 수정해야 합니다. 이 파일에는 Supabase의 모든 핵심 설정이 담겨 있습니다.

가장 중요한 설정들을 중심으로 설명해 드릴게요.

# 필수 설정: 프로젝트 전역 URL 및 키 🔑
SUPABASE_URL="https://api.yourdomain.com" # Supabase 클라이언트가 연결할 주소 (Kong 프록시를 통해 접근)
JWT_SECRET="YOUR_VERY_LONG_AND_SECURE_JWT_SECRET" # 강력한 JWT 시크릿 (매우 중요! 아래 참조)

# ANON_KEY 및 SERVICE_ROLE_KEY는 자동으로 생성되지만, 직접 설정도 가능
ANON_KEY=""
SERVICE_ROLE_KEY=""

# 내부 서비스 URL (대부분 기본값 유지)
DATABASE_URL="postgresql://postgres:postgres@db:5432/postgres"

# 외부 노출 서비스 URL (매우 중요! 커스텀 도메인으로 변경)
GOTRUE_URL="https://auth.yourdomain.com"
REALTIME_URL="https://realtime.yourdomain.com"
STORAGE_URL="https://storage.yourdomain.com"
POSTGREST_URL="https://api.yourdomain.com/rest/v1" # PostgREST는 보통 Kong을 통해 접근

# 스토리지 설정 (기본값은 로컬 스토리지)
# S3, MinIO 등으로 변경하려면 주석 해제 및 설정
# STORAGE_BACKEND=s3
# AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY_ID
# AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY
# S3_REGION=ap-northeast-2
# S3_BUCKET=your-supabase-bucket

# 이메일 전송 설정 (실제 서비스에서는 필수) 📧
# Inbucket 대신 SendGrid, Mailgun 등 SMTP 서비스 정보 입력
# SMTP_HOST=smtp.sendgrid.net
# SMTP_PORT=587
# SMTP_USER=apikey
# SMTP_PASS=YOUR_SENDGRID_API_KEY
# SITE_URL="https://yourdomain.com" # 인증 이메일의 링크 생성에 사용

# 기타 설정 (필요에 따라)
# ANALYTICS_ENABLED=true
# etc.

📝 JWT_SECRET 생성 중요성: JWT_SECRET은 Supabase의 보안 핵심입니다. 절대 짧거나 예측 가능한 문자열을 사용하지 마세요. 최소 32자 이상의 무작위 문자열을 권장하며, openssl rand -hex 32 또는 온라인 JWT 시크릿 생성기를 사용하여 생성할 수 있습니다.

예시 (터미널에서):

openssl rand -hex 32
# 결과 예시: af04bc1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c

이 값을 .env 파일의 JWT_SECRET에 붙여넣으세요.

3. Supabase 서비스 실행

.env 파일 설정이 완료되었다면, 다음 명령어로 Supabase 서비스를 시작합니다.

docker-compose up -d

이 명령은 정의된 모든 Docker 컨테이너를 백그라운드에서 시작합니다. 처음 실행 시 이미지 다운로드 등으로 시간이 다소 소요될 수 있습니다.

컨테이너가 제대로 실행되었는지 확인하려면 docker-compose ps 명령어를 사용합니다. 모든 서비스가 Up 상태여야 합니다.


🌐 API 도메인 연결 노하우 (리버스 프록시: Nginx + Let’s Encrypt)

Supabase는 기본적으로 Docker 컨테이너 내에서 실행되며, 각 서비스는 특정 포트로 노출됩니다. 외부에서 이 서비스들에 접근하고, 특히 SSL(HTTPS)을 적용하기 위해서는 리버스 프록시(Reverse Proxy) 설정이 필수적입니다. Nginx와 Let’s Encrypt를 사용하는 방법을 소개합니다.

1. DNS 설정하기

Supabase 서비스별로 서브도메인을 연결하여 관리하는 것이 일반적입니다. DNS 공급자(Cloudflare, Gabia 등)의 관리 콘솔에 접속하여 다음과 같은 A 레코드를 추가합니다. YOUR_SERVER_IP는 서버의 공인 IP 주소입니다.

Type Name Value (YOUR_SERVER_IP)
A api YOUR_SERVER_IP
A auth YOUR_SERVER_IP
A realtime YOUR_SERVER_IP
A storage YOUR_SERVER_IP

예시: api.yourdomain.com -> 서버 IP auth.yourdomain.com -> 서버 IP realtime.yourdomain.com -> 서버 IP storage.yourdomain.com -> 서버 IP

DNS 변경 사항이 전파되려면 시간이 필요할 수 있습니다 (몇 분에서 몇 시간).

2. Nginx 설치 및 설정

서버에 Nginx를 설치합니다.

sudo apt update
sudo apt install nginx -y

Nginx 설정 파일을 생성합니다. /etc/nginx/sites-available/supabase 파일을 열어 다음 내용을 추가하고 저장합니다.

# /etc/nginx/sites-available/supabase
server {
    listen 80;
    server_name api.yourdomain.com auth.yourdomain.com realtime.yourdomain.com storage.yourdomain.com;

    # Let's Encrypt 검증을 위한 설정 (나중에 Certbot 실행 시 필요)
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri; # HTTP -> HTTPS 강제 리다이렉트
    }
}

# HTTPS 설정은 Let's Encrypt로 인증서 발급 후 자동으로 생성됩니다.
# Certbot이 /etc/nginx/sites-available/supabase.conf 에 내용을 추가합니다.

설정 파일을 활성화하고 Nginx를 재시작합니다.

sudo ln -s /etc/nginx/sites-available/supabase /etc/nginx/sites-enabled/
sudo nginx -t # 설정 파일 문법 검사
sudo systemctl restart nginx

3. Let’s Encrypt (Certbot)를 통한 SSL 인증서 발급

HTTPS를 사용하기 위해 Let’s Encrypt의 무료 SSL 인증서를 발급받습니다. Certbot을 사용하면 쉽게 자동화할 수 있습니다.

sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

sudo certbot --nginx -d api.yourdomain.com -d auth.yourdomain.com -d realtime.yourdomain.com -d storage.yourdomain.com

Certbot이 인증서 발급 과정을 안내할 것입니다. 이메일 주소를 입력하고 약관에 동의하면 자동으로 Nginx 설정 파일(supabase 파일에 내용 추가 또는 supabase-le-ssl.conf 같은 새 파일 생성)이 업데이트되고 HTTPS가 활성화됩니다.

Certbot이 Nginx 설정 파일을 어떻게 수정했는지 sudo cat /etc/nginx/sites-available/supabase 또는 sudo cat /etc/nginx/sites-enabled/supabase-le-ssl.conf 명령으로 확인해 보세요. 다음과 비슷한 내용이 추가되어 있을 겁니다.

# ... (기존 HTTP 설정)

server {
    listen 443 ssl;
    server_name api.yourdomain.com; # 각 도메인별로 별도의 server 블록이 생길 수도 있음

    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Supabase 서비스별 프록시 설정 🕸️
    location / {
        proxy_pass http://localhost:8000; # Kong 프록시 (기본 Supabase 포트)
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
    # 나머지 Supabase 컴포넌트들을 위한 location 블록 추가 (예: auth.yourdomain.com)
    # location /auth { proxy_pass http://localhost:9999; ... }
    # location /storage { proxy_pass http://localhost:5000; ... }
    # Kong이 기본적으로 8000번 포트를 통해 모든 요청을 라우팅하므로,
    # 보통은 8000번으로 통일하고 Kong 내부에서 서비스 라우팅을 담당합니다.
    # 즉, `api.yourdomain.com`은 Kong으로 가고, Kong이 내부적으로 PostgREST, Auth 등으로 라우팅.
    # `auth.yourdomain.com`은 별도로 GoTrue로 직접 연결하는 방식도 가능하지만,
    # 여기서는 간결하게 Kong을 통해 모든 API를 노출하는 방식으로 진행합니다.
}

⚠️ 중요: Supabase의 docker-compose.yml은 기본적으로 Kong 프록시가 8000번 포트로 외부 노출됩니다. PostgREST는 8000번 포트의 /rest/v1 경로로, GoTrue는 /auth/v1 경로로, Storage는 /storage/v1 경로로 접근 가능합니다. 따라서 Nginx에서 proxy_pass http://localhost:8000; 하나만 설정하고 .envSUPABASE_URL을 이 Nginx 프록시 URL로 설정하는 것이 가장 일반적입니다.

최종 Nginx 설정 예시 (권장): 모든 Supabase 서비스는 Kong 프록시(http://localhost:8000)를 통해 접근하는 것이 가장 권장됩니다. .env 파일의 SUPABASE_URL을 메인 API 도메인으로 설정하고, 클라이언트에서 이 URL을 사용하면 Kong이 내부적으로 각 서비스로 라우팅합니다.

/etc/nginx/sites-available/supabase

server {
    listen 80;
    server_name api.yourdomain.com; # 모든 서브도메인을 여기에 추가하거나,
                                    # 각 서브도메인마다 별도의 server 블록을 만들어도 됩니다.

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name api.yourdomain.com; # Supabase API의 주 도메인

    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:8000; # Kong 프록시의 기본 포트
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
}

# 만약 auth.yourdomain.com, storage.yourdomain.com 등도 Nginx에서 별도로 처리하고 싶다면,
# 위 server 블록을 복사하여 server_name과 proxy_pass 포트/경로를 변경해야 합니다.
# 예: auth.yourdomain.com -> proxy_pass http://localhost:9999;
#     storage.yourdomain.com -> proxy_pass http://localhost:5000;
# 하지만 Supabase의 기본 설정은 Kong(8000)을 통해 모든 API를 노출하는 방식이므로,
# 하나의 도메인(api.yourdomain.com)으로 충분합니다.

Nginx 설정 변경 후에는 sudo nginx -t 로 문법 확인 후 sudo systemctl restart nginx 로 재시작해야 합니다.

4. Supabase .env 환경변수 최종 업데이트 및 재시작

Nginx와 SSL 설정이 완료되었다면, .env 파일의 URL들을 최종적으로 설정해 줍니다. 특히 GOTRUE_URL, REALTIME_URL, STORAGE_URL을 위에서 설정한 HTTPS 도메인으로 정확히 지정해야 합니다.

# ... (앞부분 동일)

SUPABASE_URL="https://api.yourdomain.com" # Nginx를 통해 접근할 메인 URL

# 외부 노출 서비스 URL (매우 중요! 커스텀 도메인으로 변경)
# Nginx에서 api.yourdomain.com 하나로 프록시하면,
# 내부적으로 Kong이 각 서비스로 라우팅하므로,
# 모든 URL을 'https://api.yourdomain.com'으로 통일하는 것이 간단합니다.
# Kong이 알아서 /auth/v1, /realtime/v1, /storage/v1 등으로 라우팅해줍니다.
GOTRUE_URL="https://api.yourdomain.com"
REALTIME_URL="https://api.yourdomain.com"
STORAGE_URL="https://api.yourdomain.com"
POSTGREST_URL="https://api.yourdomain.com/rest/v1" # 역시 Kong을 통해 접근

# ... (나머지 설정 동일)

.env 파일을 수정한 후에는 반드시 Supabase 컨테이너를 재시작해야 변경 사항이 적용됩니다.

docker-compose down
docker-compose up -d

📊 Supabase Dashboard 접속 및 초기 설정

Supabase의 강력한 기능 중 하나는 직관적인 대시보드입니다. 직접 구축 시에는 대시보드를 별도로 접근해야 합니다.

Supabase의 대시보드 Docker 이미지는 supabase/dashboard로 제공됩니다. 이를 실행하여 api.yourdomain.com으로 연결할 수 있습니다.

# docker-compose.yml 파일에 대시보드 서비스 추가
# (또는 별도의 docker run 명령으로 실행)
# 예시:
# dashboard:
#   image: supabase/dashboard:latest
#   ports:
#     - "8082:8082"
#   environment:
#     - SUPABASE_URL=https://api.yourdomain.com
#     - SUPABASE_ANON_KEY=YOUR_ANON_KEY_FROM_DOT_ENV
#     - SUPABASE_SERVICE_ROLE_KEY=YOUR_SERVICE_ROLE_KEY_FROM_DOT_ENV
#     - AUTH_SALT=YOUR_JWT_SECRET_FROM_DOT_ENV # JWT_SECRET과 동일하게 설정

# Nginx에 대시보드용 서브도메인 추가 (예: dashboard.yourdomain.com)
# server {
#     listen 443 ssl;
#     server_name dashboard.yourdomain.com;
#     # ... SSL 설정
#     location / {
#         proxy_pass http://localhost:8082; # 대시보드 포트
#         # ... 프록시 헤더 설정
#     }
# }

이렇게 설정한 후, https://dashboard.yourdomain.com (또는 Nginx에 설정한 포트/도메인)으로 접속하면 Supabase 대시보드를 볼 수 있습니다.

대시보드에 접속한 후, Superuser 비밀번호를 설정하거나 프로젝트를 생성하는 등의 초기 설정을 진행할 수 있습니다. PostgreSQL 데이터베이스에 직접 연결하여 관리할 수도 있습니다.


🔍 트러블슈팅 팁 및 주의사항

  • 방화벽 (Firewall): 🚨 서버의 방화벽(UFW, Security Group 등)에서 80, 443, 5432 (PostgreSQL 직접 접근 시) 포트가 외부에서 접근 가능하도록 열려 있는지 확인하세요.
  • 환경 변수 오타: .env 파일의 변수 이름이나 값에 오타가 없는지 꼼꼼히 확인하세요. 특히 URL 끝에 /가 있는지 없는지 등 작은 차이가 문제를 일으킬 수 있습니다.
  • DNS 전파 지연: DNS 변경 후 Nginx나 Supabase가 즉시 해당 도메인을 인식하지 못할 수 있습니다. dig yourdomain.com 명령 등으로 DNS가 제대로 전파되었는지 확인해 보세요.
  • 로그 확인: 📝 문제가 발생하면 docker-compose logs 명령으로 각 서비스의 로그를 확인하여 원인을 파악하세요. 특정 서비스의 로그만 보고 싶다면 docker-compose logs <서비스_이름> (예: docker-compose logs auth)을 사용합니다.
  • 리소스 부족: ☁️ 서버의 RAM이나 CPU가 부족하면 Supabase 서비스가 제대로 작동하지 않거나 느려질 수 있습니다. top 또는 htop 명령으로 리소스 사용량을 확인하세요.
  • 백업 전략: 💾 직접 구축 시에는 데이터베이스 백업이 매우 중요합니다. PostgreSQL의 pg_dump를 사용하여 정기적으로 데이터를 백업하고 안전한 곳에 보관해야 합니다.
  • 업데이트 관리: 🔄 Supabase의 Docker 이미지는 지속적으로 업데이트됩니다. 보안 패치나 새로운 기능을 적용하려면 주기적으로 git pull로 저장소를 업데이트하고 docker-compose pull & docker-compose up -d로 이미지를 최신으로 유지해야 합니다.

🎉 마무리하며

내 서버에 Supabase를 직접 구축하는 것은 초기에는 다소 복잡하게 느껴질 수 있지만, 한번 성공하고 나면 엄청난 성취감을 느낄 수 있습니다. ✨ 데이터에 대한 완전한 제어권과 유연성을 얻는 것은 개발자에게 큰 이점이죠. 이 가이드가 여러분의 Supabase 직접 구축 여정에 큰 도움이 되었기를 바랍니다!

궁금한 점이나 막히는 부분이 있다면 언제든지 커뮤니티나 공식 문서를 참고해 주세요. 행복한 개발 되세요! 😊

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다