동기화 로직 최적화 및 타입 오류 수정
- SyncState 인터페이스 개선 및 타입 오류 해결 - withRetry 함수를 네트워크 유틸리티에서 재사용하여 코드 중복 제거 - 오류 처리 및 로깅 개선 - 트랜잭션 다운로드/업로드 로직 최적화
This commit is contained in:
@@ -13,30 +13,62 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
if (!isSyncEnabled()) return;
|
||||
|
||||
try {
|
||||
console.log('서버에서 트랜잭션 데이터 다운로드 시작');
|
||||
const { data, error } = await supabase
|
||||
.from('transactions')
|
||||
.select('*')
|
||||
.eq('user_id', userId);
|
||||
console.log('[동기화] 서버에서 트랜잭션 데이터 다운로드 시작');
|
||||
|
||||
// 대용량 데이터 처리를 위한 페이지네이션 설정
|
||||
const pageSize = 500; // 한 번에 가져올 최대 레코드 수
|
||||
let lastId = null;
|
||||
let allServerData = [];
|
||||
let hasMore = true;
|
||||
|
||||
// 페이지네이션을 사용하여 모든 데이터 가져오기
|
||||
while (hasMore) {
|
||||
let query = supabase
|
||||
.from('transactions')
|
||||
.select('*')
|
||||
.eq('user_id', userId)
|
||||
.order('id', { ascending: true })
|
||||
.limit(pageSize);
|
||||
|
||||
// 마지막 ID 이후의 데이터만 가져오기
|
||||
if (lastId) {
|
||||
query = query.gt('id', lastId);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
console.error('트랜잭션 다운로드 실패:', error);
|
||||
throw error;
|
||||
const { data, error } = await query;
|
||||
|
||||
if (error) {
|
||||
console.error('[동기화] 트랜잭션 다운로드 실패:', error);
|
||||
console.error('[동기화] 오류 상세:', JSON.stringify(error, null, 2));
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
hasMore = false;
|
||||
} else {
|
||||
allServerData = [...allServerData, ...data];
|
||||
lastId = data[data.length - 1].id;
|
||||
|
||||
// 마지막 페이지인지 확인
|
||||
if (data.length < pageSize) {
|
||||
hasMore = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
console.log('서버에 저장된 트랜잭션 없음');
|
||||
if (allServerData.length === 0) {
|
||||
console.log('[동기화] 서버에 저장된 트랜잭션 없음');
|
||||
return; // 서버에 데이터가 없으면 로컬 데이터 유지
|
||||
}
|
||||
|
||||
console.log(`서버에서 ${data.length}개의 트랜잭션 다운로드`);
|
||||
console.log(`[동기화] 서버에서 ${allServerData.length}개의 트랜잭션 다운로드`);
|
||||
|
||||
// 삭제된 트랜잭션 ID 목록 가져오기
|
||||
const deletedIds = getDeletedTransactions();
|
||||
console.log(`[동기화] 삭제된 트랜잭션 ${deletedIds.length}개 필터링 적용`);
|
||||
|
||||
// 서버 데이터를 로컬 형식으로 변환 (삭제된 항목 제외)
|
||||
const serverTransactions = data
|
||||
const serverTransactions = allServerData
|
||||
.filter(t => {
|
||||
const transactionId = t.transaction_id || t.id;
|
||||
const isDeleted = deletedIds.includes(transactionId);
|
||||
@@ -46,37 +78,51 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
return !isDeleted; // 삭제된 항목 제외
|
||||
})
|
||||
.map(t => {
|
||||
// 날짜 형식 변환 시 오류 방지 처리
|
||||
let formattedDate = '날짜 없음';
|
||||
try {
|
||||
if (t.date) {
|
||||
// ISO 형식이 아닌 경우 기본 변환 수행
|
||||
if (!t.date.match(/^\d{4}-\d{2}-\d{2}T/)) {
|
||||
console.log(`비표준 날짜 형식 감지: ${t.date}, ID: ${t.transaction_id || t.id}`);
|
||||
// 유효한 Date 객체로 변환 가능한지 확인
|
||||
const testDate = new Date(t.date);
|
||||
if (isNaN(testDate.getTime())) {
|
||||
console.warn(`잘못된 날짜 형식 감지, 현재 날짜 사용: ${t.date}`);
|
||||
t.date = new Date().toISOString(); // 잘못된 날짜는 현재 날짜로 대체
|
||||
// 날짜 형식 변환 시 오류 방지 처리
|
||||
let formattedDate = '날짜 없음';
|
||||
try {
|
||||
if (t.date) {
|
||||
// ISO 형식이 아닌 경우 기본 변환 수행
|
||||
if (!t.date.match(/^\d{4}-\d{2}-\d{2}T/)) {
|
||||
console.log(`[동기화] 비표준 날짜 형식 감지: ${t.date}, ID: ${t.transaction_id || t.id}`);
|
||||
// 유효한 Date 객체로 변환 가능한지 확인
|
||||
const testDate = new Date(t.date);
|
||||
if (isNaN(testDate.getTime())) {
|
||||
console.warn(`[동기화] 잘못된 날짜 형식 감지, 현재 날짜 사용: ${t.date}`);
|
||||
t.date = new Date().toISOString(); // 잘못된 날짜는 현재 날짜로 대체
|
||||
}
|
||||
}
|
||||
formattedDate = formatDateForDisplay(t.date);
|
||||
}
|
||||
formattedDate = formatDateForDisplay(t.date);
|
||||
} catch (err) {
|
||||
console.error(`[동기화] 날짜 변환 오류 (ID: ${t.transaction_id || t.id}):`, err);
|
||||
// 오류 발생 시 기본값 사용
|
||||
formattedDate = new Date().toLocaleString('ko-KR');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`날짜 변환 오류 (ID: ${t.transaction_id || t.id}):`, err);
|
||||
// 오류 발생 시 기본값 사용
|
||||
formattedDate = new Date().toLocaleString('ko-KR');
|
||||
|
||||
return {
|
||||
id: t.transaction_id || t.id,
|
||||
title: t.title || '무제',
|
||||
amount: t.amount || 0,
|
||||
date: formattedDate,
|
||||
category: t.category || '기타',
|
||||
type: t.type || 'expense',
|
||||
notes: t.notes || ''
|
||||
};
|
||||
} catch (itemError) {
|
||||
console.error(`[동기화] 트랜잭션 변환 오류 (ID: ${t.transaction_id || t.id}):`, itemError);
|
||||
// 오류 발생 시 기본 객체 반환
|
||||
return {
|
||||
id: t.transaction_id || t.id,
|
||||
title: '데이터 오류',
|
||||
amount: 0,
|
||||
date: new Date().toLocaleString('ko-KR'),
|
||||
category: '기타',
|
||||
type: 'expense',
|
||||
notes: '데이터 변환 중 오류 발생'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: t.transaction_id || t.id,
|
||||
title: t.title,
|
||||
amount: t.amount,
|
||||
date: formattedDate,
|
||||
category: t.category,
|
||||
type: t.type,
|
||||
notes: t.notes
|
||||
};
|
||||
});
|
||||
|
||||
// 기존 로컬 데이터 불러오기
|
||||
@@ -88,12 +134,16 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
|
||||
// 로컬 데이터를 맵에 추가
|
||||
localTransactions.forEach((tx: Transaction) => {
|
||||
transactionMap.set(tx.id, tx);
|
||||
if (tx && tx.id) { // 유효성 검사 추가
|
||||
transactionMap.set(tx.id, tx);
|
||||
}
|
||||
});
|
||||
|
||||
// 서버 데이터로 맵 업데이트 (서버 데이터 우선)
|
||||
serverTransactions.forEach(tx => {
|
||||
transactionMap.set(tx.id, tx);
|
||||
if (tx && tx.id) { // 유효성 검사 추가
|
||||
transactionMap.set(tx.id, tx);
|
||||
}
|
||||
});
|
||||
|
||||
// 최종 병합된 데이터 생성
|
||||
@@ -101,12 +151,13 @@ export const downloadTransactions = async (userId: string): Promise<void> => {
|
||||
|
||||
// 로컬 스토리지에 저장
|
||||
localStorage.setItem('transactions', JSON.stringify(mergedTransactions));
|
||||
console.log(`총 ${mergedTransactions.length}개의 트랜잭션 병합 완료`);
|
||||
console.log(`[동기화] 총 ${mergedTransactions.length}개의 트랜잭션 병합 완료`);
|
||||
|
||||
// 이벤트 발생시켜 UI 업데이트
|
||||
window.dispatchEvent(new Event('transactionUpdated'));
|
||||
} catch (error) {
|
||||
console.error('트랜잭션 다운로드 중 오류:', error);
|
||||
console.error('[동기화] 트랜잭션 다운로드 중 오류:', error);
|
||||
console.error('[동기화] 오류 상세:', JSON.stringify(error, null, 2));
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user