Compare commits

...

2 Commits

Author SHA1 Message Date
hansoo
cdf2de5d9f Add migration script for Cloud to On-Prem 2025-04-28 06:19:57 +09:00
hansoo
c089195ea9 Update Java path config and upgrade Capacitor dependencies 2025-04-27 18:03:21 +09:00
5 changed files with 149 additions and 5 deletions

View File

@@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.0'
classpath 'com.android.tools.build:gradle:8.9.1'
classpath 'com.google.gms:google-services:4.4.2'
// NOTE: Do not place your application dependencies here; they belong

View File

@@ -22,7 +22,8 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
# Java 및 Kotlin 버전 설정
org.gradle.java.home=/opt/homebrew/Cellar/openjdk@17/17.0.14/libexec/openjdk.jdk/Contents/Home
# org.gradle.java.home is commented out to allow default or JAVA_HOME usage
# org.gradle.java.home=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View File

@@ -0,0 +1,80 @@
# Supabase Cloud → On-Premise Migration Plan
이 문서에는 기존 Supabase Cloud 프로젝트를 On-Premise Self-Host 환경으로 이전하기 위한 단계별 절차를 정리합니다.
## 1. 개요
- 목적: 클라우드 종속성을 제거하고 자체 운영 가능하도록 Supabase 스택을 온프레미스 환경에 배포
- 범위: 인증(Gotrue), 실시간(Realtime), 스토리지(Storage), 데이터베이스(Postgres)
## 2. 사전 준비
1. 현재 환경 문서화
- 프로젝트 구조, 스키마, RLS 규칙, 함수, 트리거 등
- 사용 중인 Supabase CLI/SDK 버전 및 환경 변수 목록
2. 인프라 준비
- Docker 엔진 또는 Kubernetes 클러스터
- 도메인, TLS 인증서 준비
- 최소 요구 사양 확인 (CPU, 메모리, 디스크)
3. 백업 계획 수립
- Cloud DB Dump 스케줄링 방법
- 백업 보관 위치 및 암호화 방침
## 3. On-Premise Supabase Self-Host 배포
1. Supabase CLI 설치
```bash
npm install -g supabase
```
2. 초기화 및 컨테이너 실행
```bash
supabase init # 프로젝트 디렉토리에 구성 파일 작성
supabase start # Postgres, Kong, Realtime, GoTrue, Storage 컨테이너 실행
```
3. 버전 호환성 확인
- `supabase version`으로 CLI, API, DB 버전 일치 여부 점검
## 4. 데이터 마이그레이션
1. Cloud DB Dump
```bash
supabase db dump --project-ref <PROJECT_REF> --file cloud_dump.sql
```
2. On-Premise DB Restore
```bash
supabase db restore --file cloud_dump.sql
```
3. 데이터 무결성 검증
- 주요 테이블 row 수 체크
- RLS 규칙·함수 정상 동작 여부 테스트
## 5. 애플리케이션 구성 변경
1. 환경 변수 업데이트
```env
SUPABASE_URL=http://<ONPREM_HOST>:8000
SUPABASE_ANON_KEY=<새_ANON_KEY>
SUPABASE_SERVICE_KEY=<새_SERVICE_KEY>
```
2. SDK 초기화 점검
- `client = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)` 정상 연결 확인
## 6. 테스트 및 검증
1. 로컬 개발서버 테스트
- 프론트·백엔드 실행 후 CRUD 기능 확인
2. 스테이징 환경 배포
- Blue-Green 또는 Canary 배포로 트래픽 분할
- 모니터링(로그, 메트릭) 이상 유무 확인
## 7. 프로덕션 전환
1. DNS 레코드 변경 또는 로드밸런서 설정
2. SSL/TLS 인증서 적용
3. 전환 후 롤백 플랜 준비
## 8. 롤백 계획
- 문제가 발생 시 이전 Cloud 인스턴스로 트래픽 리디렉션
- 신규 데이터 백업 및 차분 마이그레이션
## 9. 모니터링 및 운영
- 백그라운드 컨테이너 상태 감시 (Prometheus, Grafana)
- 정기 백업·복원 테스트 자동화
- 보안 패치 및 버전 업데이트 정책 수립
---
*문서 위치: `docs/SUPABASE_ONPREM_MIGRATION_PLAN.md`*

View File

@@ -24,10 +24,10 @@ EXTERNAL SOURCES:
:path: "../../node_modules/@capacitor/splash-screen"
SPEC CHECKSUMS:
Capacitor: 68ff8eabbcce387e69767c13b5fbcc1c5399eabc
Capacitor: bceb785fb78f5e81e4a9e37843bc1c24bd9c7194
CapacitorCordova: 866217f32c1d25b326c568a10ea3ed0c36b13e29
CapacitorKeyboard: 2c26c6fccde35023c579fc37d4cae6326d5e6343
CapacitorSplashScreen: f4e58cc02aafd91c7cbaf32a3d1b44d02a115125
CapacitorKeyboard: 4db71e694e7afb5d7c0be09b05495c19f7d6c914
CapacitorSplashScreen: 7e7a0a1113833032f196b3af6fa437baccacf5bc
PODFILE CHECKSUM: 7376e84e32edf2d1753401ce95b6db45439d33ff

63
src/lib/migrateData.ts Normal file
View File

@@ -0,0 +1,63 @@
import dotenv from 'dotenv';
import { createClient } from '@supabase/supabase-js';
dotenv.config();
const cloudUrl = process.env.CLOUD_SUPABASE_URL;
// 서비스 역할 키가 유효하지 않으면 CLOUD_SUPABASE_ANON_KEY 또는 VITE_SUPABASE_ANON_KEY를 사용합니다.
const cloudKey = process.env.CLOUD_SUPABASE_SERVICE_ROLE_KEY || process.env.CLOUD_SUPABASE_ANON_KEY || process.env.VITE_SUPABASE_ANON_KEY;
const onpremUrl = process.env.ONPREM_SUPABASE_URL;
// 서비스 역할 키가 유효하지 않으면 ONPREM_SUPABASE_ANON_KEY 또는 VITE_SUPABASE_ANON_KEY를 사용합니다.
const onpremKey = process.env.ONPREM_SUPABASE_SERVICE_ROLE_KEY || process.env.ONPREM_SUPABASE_ANON_KEY || process.env.VITE_SUPABASE_ANON_KEY;
if (!cloudUrl || !cloudKey || !onpremUrl || !onpremKey) {
console.error('환경 변수가 설정되지 않았습니다. .env 파일을 확인하세요.');
process.exit(1);
}
const cloud = createClient(cloudUrl, cloudKey);
const onprem = createClient(onpremUrl, onpremKey);
// 복사할 테이블 목록을 정의하세요.
const tables = [
'users',
'accounts',
'transactions',
// 필요에 따라 추가 테이블을 여기에 입력
];
async function migrateTable(table: string) {
console.log(`Migrating table: ${table}`);
const { data, error } = await cloud.from(table).select('*');
if (error) {
// 테이블이 없으면 스킵
if (error.code === '42P01') {
console.warn(`Table ${table} not found in Cloud DB, skipping.`);
return;
}
console.error(`Error fetching ${table}:`, error);
return;
}
if (!data || data.length === 0) {
console.log(`${table} has no data to migrate.`);
return;
}
const { error: insertError } = await onprem.from(table).upsert(data);
if (insertError) {
console.error(`Error inserting into ${table}:`, insertError);
} else {
console.log(`Migrated ${data.length} rows into ${table}`);
}
}
async function main() {
for (const table of tables) {
await migrateTable(table);
}
console.log('Migration complete.');
}
main().catch(err => {
console.error('Migration failed:', err);
process.exit(1);
});