diff --git a/src/hooks/sync/syncBackupUtils.ts b/src/hooks/sync/syncBackupUtils.ts new file mode 100644 index 0000000..1146517 --- /dev/null +++ b/src/hooks/sync/syncBackupUtils.ts @@ -0,0 +1,52 @@ + +/** + * 로컬 데이터 백업 만들기 + */ +export const createLocalDataBackup = () => { + const budgetDataBackup = localStorage.getItem('budgetData'); + const categoryBudgetsBackup = localStorage.getItem('categoryBudgets'); + const transactionsBackup = localStorage.getItem('transactions'); + + console.log('로컬 데이터 백업:', { + budgetData: budgetDataBackup ? '있음' : '없음', + categoryBudgets: categoryBudgetsBackup ? '있음' : '없음', + transactions: transactionsBackup ? '있음' : '없음' + }); + + return { + budgetDataBackup, + categoryBudgetsBackup, + transactionsBackup + }; +}; + +/** + * 로컬 데이터 복원하기 + */ +export const restoreLocalDataBackup = (backup: { + budgetDataBackup: string | null, + categoryBudgetsBackup: string | null, + transactionsBackup: string | null +}) => { + const { budgetDataBackup, categoryBudgetsBackup, transactionsBackup } = backup; + + console.log('로컬 데이터 복원 시도'); + + // 오류 발생 시 백업 데이터 복원 + if (budgetDataBackup) { + localStorage.setItem('budgetData', budgetDataBackup); + } + if (categoryBudgetsBackup) { + localStorage.setItem('categoryBudgets', categoryBudgetsBackup); + } + if (transactionsBackup) { + localStorage.setItem('transactions', transactionsBackup); + } + + // 이벤트 발생시켜 UI 업데이트 + window.dispatchEvent(new Event('budgetDataUpdated')); + window.dispatchEvent(new Event('categoryBudgetsUpdated')); + window.dispatchEvent(new Event('transactionUpdated')); + + console.log('로컬 데이터 복원 완료'); +}; diff --git a/src/hooks/sync/syncNetworkChecker.ts b/src/hooks/sync/syncNetworkChecker.ts new file mode 100644 index 0000000..0a5b324 --- /dev/null +++ b/src/hooks/sync/syncNetworkChecker.ts @@ -0,0 +1,45 @@ + +import { checkNetworkStatus } from '@/utils/network/checker'; +import { toast } from '@/hooks/useToast.wrapper'; + +/** + * 동기화를 위한 네트워크 상태 확인 + */ +export const checkSyncNetworkStatus = async (): Promise => { + // 기본 네트워크 상태 확인 - navigator.onLine 우선 사용 + const navigatorOnline = navigator.onLine; + console.log(`[동기화] 기본 네트워크 상태 확인: ${navigatorOnline ? '온라인' : '오프라인'}`); + + if (!navigatorOnline) { + return false; + } + + // 강화된 네트워크 확인 시도 (실패해도 계속 진행) + try { + const isOnline = await checkNetworkStatus(); + console.log(`[동기화] 강화된 네트워크 확인 결과: ${isOnline ? '온라인' : '오프라인'}`); + return isOnline; + } catch (error) { + // 네트워크 확인 실패해도 navigator.onLine이 true면 진행 + console.warn('[동기화] 강화된 네트워크 확인 실패, 기본 상태 사용:', error); + return navigatorOnline; + } +}; + +/** + * 네트워크 오류 시 알림 표시 + */ +export const showNetworkErrorNotification = ( + addNotification: (title: string, message: string) => void +) => { + const title = "네트워크 연결 필요"; + const description = "동기화를 위해 인터넷 연결이 필요합니다."; + + toast({ + title, + description, + variant: "destructive" + }); + + addNotification(title, description); +}; diff --git a/src/hooks/sync/syncPerformer.ts b/src/hooks/sync/syncPerformer.ts new file mode 100644 index 0000000..bcd0daa --- /dev/null +++ b/src/hooks/sync/syncPerformer.ts @@ -0,0 +1,47 @@ + +import { trySyncAllData } from '@/utils/syncUtils'; +import { setLastSyncTime } from '@/utils/syncUtils'; + +/** + * 실제 동기화 수행 함수 (최대 2회까지 자동 재시도) + */ +export const performSync = async (userId: string) => { + if (!userId) return; + + let attempts = 0; + const maxAttempts = 2; + + while (attempts < maxAttempts) { + try { + attempts++; + console.log(`동기화 시도 ${attempts}/${maxAttempts}`); + + // 네트워크 상태 확인 - 기본 navigator.onLine 사용 + if (!navigator.onLine) { + console.log('네트워크 연결 없음, 동기화 건너뜀'); + throw new Error('네트워크 연결 필요'); + } + + const result = await trySyncAllData(userId); + + // 동기화 성공 시 마지막 동기화 시간 업데이트 + if (result && result.success) { + const currentTime = new Date().toISOString(); + console.log('동기화 성공, 시간 업데이트:', currentTime); + setLastSyncTime(currentTime); + } + + return result; + } catch (error) { + console.error(`동기화 시도 ${attempts} 실패:`, error); + + if (attempts < maxAttempts) { + // 재시도 전 잠시 대기 + await new Promise(resolve => setTimeout(resolve, 2000)); + console.log(`${attempts+1}번째 동기화 재시도 중...`); + } else { + throw error; + } + } + } +}; diff --git a/src/hooks/sync/useSyncToggle.ts b/src/hooks/sync/useSyncToggle.ts index e29b1df..6414b19 100644 --- a/src/hooks/sync/useSyncToggle.ts +++ b/src/hooks/sync/useSyncToggle.ts @@ -5,12 +5,13 @@ import { toast } from '@/hooks/useToast.wrapper'; import { isSyncEnabled, setSyncEnabled, - trySyncAllData, setLastSyncTime } from '@/utils/syncUtils'; import useNotifications from '@/hooks/useNotifications'; import { resetSyncFailureCount } from './syncResultHandler'; -import { checkNetworkStatus } from '@/utils/network/checker'; +import { checkSyncNetworkStatus, showNetworkErrorNotification } from './syncNetworkChecker'; +import { performSync } from './syncPerformer'; +import { createLocalDataBackup, restoreLocalDataBackup } from './syncBackupUtils'; /** * 동기화 토글 기능을 위한 커스텀 훅 @@ -78,58 +79,17 @@ export const useSyncToggle = () => { } try { - // 네트워크 상태 확인 - navigator.onLine 우선 사용 - const navigatorOnline = navigator.onLine; - console.log(`[동기화] 기본 네트워크 상태 확인: ${navigatorOnline ? '온라인' : '오프라인'}`); - - if (checked && !navigatorOnline) { - toast({ - title: "네트워크 연결 필요", - description: "동기화를 위해 인터넷 연결이 필요합니다.", - variant: "destructive" - }); - - addNotification( - "네트워크 연결 필요", - "동기화를 위해 인터넷 연결이 필요합니다." - ); - return; - } - - // 강화된 네트워크 확인 시도 (실패해도 계속 진행) - try { - const isOnline = await checkNetworkStatus(); - console.log(`[동기화] 강화된 네트워크 확인 결과: ${isOnline ? '온라인' : '오프라인'}`); - - // 두 번째 확인에서도 오프라인이면 중단 - if (checked && !isOnline) { - toast({ - title: "네트워크 연결 필요", - description: "동기화를 위해 인터넷 연결이 필요합니다.", - variant: "destructive" - }); - - addNotification( - "네트워크 연결 필요", - "동기화를 위해 인터넷 연결이 필요합니다." - ); + // 네트워크 상태 확인 + if (checked) { + const isOnline = await checkSyncNetworkStatus(); + if (!isOnline) { + showNetworkErrorNotification(addNotification); return; } - } catch (error) { - // 네트워크 확인 실패해도 navigator.onLine이 true면 진행 - console.warn('[동기화] 강화된 네트워크 확인 실패, 기본 상태 사용:', error); } // 현재 로컬 데이터 백업 - const budgetDataBackup = localStorage.getItem('budgetData'); - const categoryBudgetsBackup = localStorage.getItem('categoryBudgets'); - const transactionsBackup = localStorage.getItem('transactions'); - - console.log('동기화 설정 변경 전 로컬 데이터 백업:', { - budgetData: budgetDataBackup ? '있음' : '없음', - categoryBudgets: categoryBudgetsBackup ? '있음' : '없음', - transactions: transactionsBackup ? '있음' : '없음' - }); + const dataBackup = createLocalDataBackup(); // 동기화 설정 변경 setEnabled(checked); @@ -152,32 +112,12 @@ export const useSyncToggle = () => { if (checked && user) { try { // 동기화 수행 - const result = await performSync(user.id); - - // 동기화 성공 시 마지막 동기화 시간 업데이트 - if (result && result.success) { - const currentTime = new Date().toISOString(); - console.log('동기화 활성화 후 첫 동기화 성공, 시간 업데이트:', currentTime); - setLastSyncTime(currentTime); - } + await performSync(user.id); } catch (error) { console.error('동기화 중 오류, 로컬 데이터 복원 시도:', error); // 오류 발생 시 백업 데이터 복원 - if (budgetDataBackup) { - localStorage.setItem('budgetData', budgetDataBackup); - } - if (categoryBudgetsBackup) { - localStorage.setItem('categoryBudgets', categoryBudgetsBackup); - } - if (transactionsBackup) { - localStorage.setItem('transactions', transactionsBackup); - } - - // 이벤트 발생시켜 UI 업데이트 - window.dispatchEvent(new Event('budgetDataUpdated')); - window.dispatchEvent(new Event('categoryBudgetsUpdated')); - window.dispatchEvent(new Event('transactionUpdated')); + restoreLocalDataBackup(dataBackup); toast({ title: "동기화 오류", @@ -203,37 +143,3 @@ export const useSyncToggle = () => { return { enabled, setEnabled, handleSyncToggle }; }; - -// 실제 동기화 수행 함수 (최대 2회까지 자동 재시도) -const performSync = async (userId: string) => { - if (!userId) return; - - let attempts = 0; - const maxAttempts = 2; - - while (attempts < maxAttempts) { - try { - attempts++; - console.log(`동기화 시도 ${attempts}/${maxAttempts}`); - - // 네트워크 상태 확인 - 기본 navigator.onLine 사용 - if (!navigator.onLine) { - console.log('네트워크 연결 없음, 동기화 건너뜀'); - throw new Error('네트워크 연결 필요'); - } - - const result = await trySyncAllData(userId); - return result; - } catch (error) { - console.error(`동기화 시도 ${attempts} 실패:`, error); - - if (attempts < maxAttempts) { - // 재시도 전 잠시 대기 - await new Promise(resolve => setTimeout(resolve, 2000)); - console.log(`${attempts+1}번째 동기화 재시도 중...`); - } else { - throw error; - } - } - } -};