# 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. 문제 발생 시 개발팀에 즉시 보고하세요.