277 lines
7.9 KiB
Markdown
277 lines
7.9 KiB
Markdown
# Appwrite 전환 가이드
|
|
|
|
## 개요
|
|
|
|
Zellyy Finance는 백엔드 서비스를 Supabase에서 Appwrite로 전환합니다. 이 문서는 전환 과정과 새로운 코드 구조에 대한 가이드를 제공합니다.
|
|
|
|
## 전환 이유
|
|
|
|
1. **더 나은 성능**: Appwrite는 경량화된 서비스로 더 빠른 응답 시간 제공
|
|
2. **확장성**: 사용자 증가에 따른 확장성 개선
|
|
3. **기능 세트**: Appwrite의 실시간 데이터베이스와 인증 시스템 활용
|
|
4. **유지보수 용이성**: 단일 백엔드 서비스로 통합하여 유지보수 간소화
|
|
|
|
## 코드 구조
|
|
|
|
```
|
|
src/
|
|
├── lib/
|
|
│ ├── appwrite/ (Appwrite 서비스)
|
|
│ │ ├── index.ts (단일 진입점)
|
|
│ │ ├── client.ts (클라이언트 설정)
|
|
│ │ ├── config.ts (환경 설정)
|
|
│ │ └── setup.ts (데이터베이스 설정)
|
|
│ └── capacitor/ (네이티브 기능)
|
|
│ ├── index.ts (단일 진입점)
|
|
│ ├── buildInfo.ts (빌드 정보 관련)
|
|
│ ├── notification.ts (알림 관련)
|
|
│ └── permissions.ts (권한 관련)
|
|
├── hooks/
|
|
│ ├── auth/
|
|
│ │ └── useAppwriteAuth.ts (인증 관련 훅)
|
|
│ └── transactions/
|
|
│ └── useAppwriteTransactions.ts (트랜잭션 관련 훅)
|
|
├── components/
|
|
│ ├── auth/
|
|
│ │ └── AppwriteConnectionStatus.tsx (연결 상태 표시)
|
|
│ ├── migration/
|
|
│ │ └── SupabaseToAppwriteMigration.tsx (마이그레이션 도구)
|
|
│ └── native/
|
|
│ ├── PermissionRequest.tsx (권한 요청 UI)
|
|
│ └── NotificationSettings.tsx (알림 설정 UI)
|
|
└── utils/
|
|
└── appwriteTransactionUtils.ts (트랜잭션 유틸리티)
|
|
```
|
|
|
|
## 환경 설정
|
|
|
|
`.env` 파일에 다음 환경 변수를 설정합니다:
|
|
|
|
```
|
|
# Appwrite 설정
|
|
VITE_APPWRITE_ENDPOINT=https://a11.ism.kr/v1
|
|
VITE_APPWRITE_PROJECT_ID=zellyy-finance
|
|
VITE_APPWRITE_DATABASE_ID=zellyy-finance
|
|
VITE_APPWRITE_TRANSACTIONS_COLLECTION_ID=transactions
|
|
|
|
# 네이티브 설정
|
|
VITE_ANDROID_MIN_API_LEVEL=21
|
|
VITE_ANDROID_TARGET_API_LEVEL=33
|
|
VITE_ANDROID_NOTIFICATION_CHANNEL_ID=zellyy_finance_notifications
|
|
```
|
|
|
|
## 마이그레이션 단계
|
|
|
|
1. **데이터베이스 설정**
|
|
- Appwrite 데이터베이스 및 컬렉션 생성
|
|
- 필요한 인덱스 및 권한 설정
|
|
|
|
2. **인증 시스템 전환**
|
|
- Appwrite 인증 시스템 설정
|
|
- 사용자 계정 마이그레이션
|
|
|
|
3. **데이터 마이그레이션**
|
|
- 트랜잭션 데이터 마이그레이션
|
|
- 데이터 무결성 검증
|
|
|
|
4. **Supabase 코드 제거**
|
|
- 마이그레이션 완료 후 Supabase 관련 코드 제거
|
|
- 환경 변수 정리
|
|
|
|
## 주요 컴포넌트 및 훅
|
|
|
|
### 1. Appwrite 클라이언트 설정
|
|
|
|
```typescript
|
|
// src/lib/appwrite/client.ts
|
|
import { Client, Account, Databases, Storage } from 'appwrite';
|
|
import { config } from './config';
|
|
|
|
// 클라이언트 초기화
|
|
export const client = new Client()
|
|
.setEndpoint(config.endpoint)
|
|
.setProject(config.projectId);
|
|
|
|
// 서비스 초기화
|
|
export const account = new Account(client);
|
|
export const databases = new Databases(client);
|
|
export const storage = new Storage(client);
|
|
```
|
|
|
|
### 2. 인증 훅
|
|
|
|
```typescript
|
|
// src/hooks/auth/useAppwriteAuth.ts
|
|
import { useState, useEffect } from 'react';
|
|
import { account } from '../../lib/appwrite';
|
|
|
|
export const useAppwriteAuth = () => {
|
|
const [user, setUser] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
// 사용자 세션 확인
|
|
useEffect(() => {
|
|
const checkSession = async () => {
|
|
try {
|
|
const session = await account.getSession('current');
|
|
if (session) {
|
|
const currentUser = await account.get();
|
|
setUser(currentUser);
|
|
}
|
|
} catch (error) {
|
|
console.error('세션 확인 오류:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
checkSession();
|
|
}, []);
|
|
|
|
// 로그인 함수
|
|
const login = async (email, password) => {
|
|
try {
|
|
await account.createEmailSession(email, password);
|
|
const currentUser = await account.get();
|
|
setUser(currentUser);
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error('로그인 오류:', error);
|
|
return { success: false, error };
|
|
}
|
|
};
|
|
|
|
// 로그아웃 함수
|
|
const logout = async () => {
|
|
try {
|
|
await account.deleteSession('current');
|
|
setUser(null);
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error('로그아웃 오류:', error);
|
|
return { success: false, error };
|
|
}
|
|
};
|
|
|
|
return { user, loading, login, logout };
|
|
};
|
|
```
|
|
|
|
### 3. 트랜잭션 훅
|
|
|
|
```typescript
|
|
// src/hooks/transactions/useAppwriteTransactions.ts
|
|
import { useState, useEffect, useCallback } from 'react';
|
|
import { databases } from '../../lib/appwrite';
|
|
import { config } from '../../lib/appwrite/config';
|
|
import { Query } from 'appwrite';
|
|
|
|
export const useAppwriteTransactions = (userId) => {
|
|
const [transactions, setTransactions] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
// 트랜잭션 불러오기
|
|
const fetchTransactions = useCallback(async () => {
|
|
if (!userId) return;
|
|
|
|
try {
|
|
setLoading(true);
|
|
const response = await databases.listDocuments(
|
|
config.databaseId,
|
|
config.transactionsCollectionId,
|
|
[Query.equal('userId', userId)]
|
|
);
|
|
setTransactions(response.documents);
|
|
} catch (error) {
|
|
console.error('트랜잭션 불러오기 오류:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [userId]);
|
|
|
|
// 초기 데이터 로드
|
|
useEffect(() => {
|
|
fetchTransactions();
|
|
}, [fetchTransactions]);
|
|
|
|
// 트랜잭션 추가
|
|
const addTransaction = async (transaction) => {
|
|
try {
|
|
const newTransaction = await databases.createDocument(
|
|
config.databaseId,
|
|
config.transactionsCollectionId,
|
|
'unique()',
|
|
{
|
|
...transaction,
|
|
userId,
|
|
createdAt: new Date().toISOString(),
|
|
}
|
|
);
|
|
setTransactions((prev) => [...prev, newTransaction]);
|
|
return { success: true, transaction: newTransaction };
|
|
} catch (error) {
|
|
console.error('트랜잭션 추가 오류:', error);
|
|
return { success: false, error };
|
|
}
|
|
};
|
|
|
|
// 트랜잭션 업데이트
|
|
const updateTransaction = async (id, data) => {
|
|
try {
|
|
const updatedTransaction = await databases.updateDocument(
|
|
config.databaseId,
|
|
config.transactionsCollectionId,
|
|
id,
|
|
data
|
|
);
|
|
setTransactions((prev) =>
|
|
prev.map((t) => (t.$id === id ? updatedTransaction : t))
|
|
);
|
|
return { success: true, transaction: updatedTransaction };
|
|
} catch (error) {
|
|
console.error('트랜잭션 업데이트 오류:', error);
|
|
return { success: false, error };
|
|
}
|
|
};
|
|
|
|
// 트랜잭션 삭제
|
|
const deleteTransaction = async (id) => {
|
|
try {
|
|
await databases.deleteDocument(
|
|
config.databaseId,
|
|
config.transactionsCollectionId,
|
|
id
|
|
);
|
|
setTransactions((prev) => prev.filter((t) => t.$id !== id));
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error('트랜잭션 삭제 오류:', error);
|
|
return { success: false, error };
|
|
}
|
|
};
|
|
|
|
return {
|
|
transactions,
|
|
loading,
|
|
fetchTransactions,
|
|
addTransaction,
|
|
updateTransaction,
|
|
deleteTransaction,
|
|
};
|
|
};
|
|
```
|
|
|
|
## 마이그레이션 도구 사용법
|
|
|
|
1. 설정 페이지에서 "Appwrite 설정" 메뉴 선택
|
|
2. "Supabase에서 Appwrite로 마이그레이션" 섹션에서 "마이그레이션 시작" 버튼 클릭
|
|
3. 마이그레이션 진행 상황 확인
|
|
4. 완료 후 데이터 검증
|
|
|
|
## 주의사항
|
|
|
|
1. 마이그레이션 중에는 데이터 변경을 최소화하세요.
|
|
2. 마이그레이션 전에 데이터 백업을 수행하세요.
|
|
3. 마이그레이션 후 모든 기능이 정상 작동하는지 테스트하세요.
|
|
4. 문제 발생 시 개발팀에 즉시 보고하세요.
|