환경변수와 배포
로컬, Vercel, 분리 서비스 배포에서 필요한 환경변수와 운영 토글을 정리합니다.
리옵트 데이터는 하나의 Next.js 앱으로도 돌릴 수 있고, control/query/realtime/export plane을 분리해서 운영할 수도 있어요. 이 문서는 환경변수를 어떤 배포 형태에서 채워야 하는지 빠르게 판단하는 기준입니다.
반드시 준비할 값
로컬과 운영 모두 PostgreSQL, Redis, 세션 비밀값이 필요합니다.
| 변수 | 언제 필요한가요? | 기준 |
|---|---|---|
POSTGRES_PROVIDER | 선택 | neon / clickhouse / default. 비우면 호스트로 감지 |
DATABASE_URL | provider ≠ clickhouse | postgresql:// 또는 postgres:// URL |
CH_POSTGRES_URL | provider = clickhouse | PgBouncer(6432) URL. 마이그레이션은 자동으로 5432 사용 |
CH_POSTGRES_CA_CERT | provider = clickhouse | 인라인 PEM. production에서 필수(서버 인증서 검증) |
REDIS_URL | 항상 | 로컬 기본값은 redis://localhost:6379 |
SESSION_SECRET | 항상 | 32자 이상, production에서 placeholder 금지 |
COOKIE_SECRET | 항상 | 32자 이상, production에서 placeholder 금지 |
NEXT_PUBLIC_SITE_URL | 항상 | OAuth callback, Stripe redirect, canonical URL 기준 |
CRON_SECRET | production cron 보호 | cron/replay/status route의 Authorization: Bearer ... 값 |
production에서는 DATABASE_URL, REDIS_URL, NEXT_PUBLIC_SITE_URL, ClickHouse 사용 시 CLICKHOUSE_URL이 localhost를 가리키면 안 됩니다.
인증과 접근 제어
로그인은 Reopt Brandapp OAuth로 시작하고, 완료 후 로컬 reopt_session 쿠키 세션으로 이어집니다.
필수 값:
BRANDAPP_CLIENT_IDBRANDAPP_CLIENT_SECRETBRANDAPP_IDBETTER_AUTH_SECRET
선택 값:
BETTER_AUTH_URL: 비워두면NEXT_PUBLIC_SITE_URL을 사용합니다.BETTER_AUTH_TRUSTED_ORIGINS: 쉼표로 구분한 Origin 목록입니다.REOPT_BASE_URL,REOPT_ID_BASE_URL: 자체 호스팅 Reopt 인스턴스를 쓸 때만 설정합니다.
production 배포에서는 현재 private beta allowlist를 통과한 이메일만 로그인할 수 있습니다.
허용되지 않은 사용자는 /waitlist로 이동합니다.
분석 백엔드
ANALYTICS_BACKEND로 분석 저장소를 고릅니다.
| 값 | 필요한 변수 | 사용 상황 |
|---|---|---|
motherduck | MOTHERDUCK_TOKEN, MOTHERDUCK_DATABASE | 기본 백엔드, MotherDuck cloud 운영 |
motherduck + local | MOTHERDUCK_LOCAL_PATH | 로컬 DuckDB 파일 또는 :memory: 검증 |
clickhouse | CLICKHOUSE_URL, CLICKHOUSE_DATABASE, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD | ClickHouse를 직접 운영할 때 |
MOTHERDUCK_LOCAL_PATH가 있으면 cloud token보다 우선합니다. 이 모드는 로컬 개발/검증용이며 production 환경 검증에서는 허용하지 않습니다.
cloud bootstrap을 직접 제어해야 하면 MOTHERDUCK_HOST, MOTHERDUCK_BOOTSTRAP_DATABASE를 추가로 사용할 수 있습니다.
네이티브 DuckDB 모드(로컬)에서 리소스 제한을 조정하려면:
| 변수 | 기본값 | 설명 |
|---|---|---|
DUCKDB_MEMORY_LIMIT | 512MB | DuckDB 메모리 상한 |
DUCKDB_THREADS | 4 | DuckDB 워커 스레드 수 |
Service plane 배포
apps/web은 service URL이 비어 있으면 내부 fallback route로 처리합니다.
외부에 분리 배포한 서비스가 있을 때만 아래 값을 채우세요.
CONTROL_API_URLQUERY_API_URLREALTIME_SERVICE_URLEXPORT_SERVICE_URL
Vercel production에서는 다음 두 프로필 중 하나를 명시적으로 선택해야 합니다.
- 단일 앱 배포: service URL을 비우고
ALLOW_INLINE_PLANES=1을 설정합니다. - 분리 배포:
CONTROL_API_URL과QUERY_API_URL을 실제 upstream 주소로 설정합니다.
두 값이 모두 비어 있으면서 ALLOW_INLINE_PLANES도 없으면 production 환경 검증이 실패합니다.
Vercel Queue와 cron
Vercel Queue topic은 apps/web/vercel.json의 ingest-events와 맞아야 합니다.
VERCEL_INGEST_TOPIC을 설정한다면 값도 ingest-events여야 합니다.
Vercel cron은 다음 route를 호출합니다.
/api/cron/evaluate-alerts/api/cron/sync-usage/api/cron/process-ingest/replay-unmaterialized
외부에서 cron/replay/status route를 호출할 때는 Authorization: Bearer $CRON_SECRET을 보내야 합니다.
각 cron은 Redis lock을 사용해 같은 작업이 겹쳐 실행되지 않게 합니다.
Billing, 알림, 제한값
Stripe checkout과 billing portal을 쓰려면 다음 값을 채웁니다.
STRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETSTRIPE_PRICE_STARTER_MONTHLYSTRIPE_PRICE_GROWTH_MONTHLY
알림 이메일을 보내려면 다음 값을 설정합니다.
RESEND_API_KEYALERT_EMAIL_FROM
운영 제한값:
CLICKHOUSE_MAX_OPEN_CONNECTIONSREDIS_CONNECT_TIMEOUT_MSREALTIME_STREAM_MAX_MSEXPORT_MAX_ROWS
주의할 점
serverSecret,STRIPE_SECRET_KEY,BRANDAPP_CLIENT_SECRET,BETTER_AUTH_SECRET,CRON_SECRET은 브라우저 번들에 들어가면 안 됩니다.- Vercel 단독 배포와 분리 plane 배포는 환경변수 전략이 다릅니다. service URL을 채우면
apps/web은 해당 upstream으로 proxy합니다. ALLOW_INLINE_PLANES=1은 Vercel에서 web function이 control/query 요청까지 직접 처리하도록 허용하는 운영 선택입니다.MOTHERDUCK_LOCAL_PATH=:memory:는 프로세스가 끝나면 데이터가 사라집니다. production에서는MOTHERDUCK_TOKEN과MOTHERDUCK_DATABASE를 사용하세요.
다음 단계
- 실행 명령은 로컬 개발
- endpoint 경계는 서비스 Plane과 엔드포인트
- 분석 저장소 선택은 분석 백엔드 선택