7.9 KiB
7.9 KiB
Appwrite 전환 가이드
개요
Zellyy Finance는 백엔드 서비스를 Supabase에서 Appwrite로 전환합니다. 이 문서는 전환 과정과 새로운 코드 구조에 대한 가이드를 제공합니다.
전환 이유
- 더 나은 성능: Appwrite는 경량화된 서비스로 더 빠른 응답 시간 제공
- 확장성: 사용자 증가에 따른 확장성 개선
- 기능 세트: Appwrite의 실시간 데이터베이스와 인증 시스템 활용
- 유지보수 용이성: 단일 백엔드 서비스로 통합하여 유지보수 간소화
코드 구조
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
마이그레이션 단계
-
데이터베이스 설정
- Appwrite 데이터베이스 및 컬렉션 생성
- 필요한 인덱스 및 권한 설정
-
인증 시스템 전환
- Appwrite 인증 시스템 설정
- 사용자 계정 마이그레이션
-
데이터 마이그레이션
- 트랜잭션 데이터 마이그레이션
- 데이터 무결성 검증
-
Supabase 코드 제거
- 마이그레이션 완료 후 Supabase 관련 코드 제거
- 환경 변수 정리
주요 컴포넌트 및 훅
1. Appwrite 클라이언트 설정
// 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. 인증 훅
// 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. 트랜잭션 훅
// 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,
};
};
마이그레이션 도구 사용법
- 설정 페이지에서 "Appwrite 설정" 메뉴 선택
- "Supabase에서 Appwrite로 마이그레이션" 섹션에서 "마이그레이션 시작" 버튼 클릭
- 마이그레이션 진행 상황 확인
- 완료 후 데이터 검증
주의사항
- 마이그레이션 중에는 데이터 변경을 최소화하세요.
- 마이그레이션 전에 데이터 백업을 수행하세요.
- 마이그레이션 후 모든 기능이 정상 작동하는지 테스트하세요.
- 문제 발생 시 개발팀에 즉시 보고하세요.