From f9aec98a45f0046d1e59eaa62e8e6157d0e465a1 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 12:35:59 +0000 Subject: [PATCH] Refactor: Split Supabase tests Splits the Supabase tests into smaller modules for better readability and maintainability. --- src/lib/supabase/tests.ts | 239 ------------------------ src/lib/supabase/tests/apiTests.ts | 127 +++++++++++++ src/lib/supabase/tests/authTests.ts | 45 +++++ src/lib/supabase/tests/databaseTests.ts | 31 +++ src/lib/supabase/tests/index.ts | 108 +++++++++++ src/lib/supabase/tests/types.ts | 33 ++++ 6 files changed, 344 insertions(+), 239 deletions(-) delete mode 100644 src/lib/supabase/tests.ts create mode 100644 src/lib/supabase/tests/apiTests.ts create mode 100644 src/lib/supabase/tests/authTests.ts create mode 100644 src/lib/supabase/tests/databaseTests.ts create mode 100644 src/lib/supabase/tests/index.ts create mode 100644 src/lib/supabase/tests/types.ts diff --git a/src/lib/supabase/tests.ts b/src/lib/supabase/tests.ts deleted file mode 100644 index 367995c..0000000 --- a/src/lib/supabase/tests.ts +++ /dev/null @@ -1,239 +0,0 @@ - -import { supabase } from './client'; -import { getSupabaseUrl, getSupabaseKey, getOriginalSupabaseUrl, isCorsProxyEnabled, getProxyType } from './config'; - -// 테스트용 직접 로그인 함수 (디버깅 전용) -export const testSupabaseLogin = async (email: string, password: string) => { - try { - console.log('테스트 로그인 시도:', email); - - const { data, error } = await supabase.auth.signInWithPassword({ - email, - password - }); - - if (error) { - console.error('테스트 로그인 오류:', error); - return { success: false, error }; - } - - console.log('테스트 로그인 성공:', data); - return { success: true, data }; - } catch (err) { - console.error('테스트 로그인 중 예외 발생:', err); - return { success: false, error: err }; - } -}; - -// API 테스트 도우미 함수 -export const testSupabaseConnection = async () => { - const originalUrl = getOriginalSupabaseUrl(); - const proxyUrl = getSupabaseUrl(); - const usingProxy = isCorsProxyEnabled(); - const proxyType = getProxyType(); - const supabaseKey = getSupabaseKey(); - - const results = { - url: originalUrl, // 원본 URL - proxyUrl: proxyUrl, // 프록시 적용된 URL - usingProxy: usingProxy, // 프록시 사용 여부 - proxyType: proxyType, // 프록시 유형 - client: !!supabase, - restApi: false, - auth: false, - database: false, - errors: [] as string[], - debugInfo: { - originalUrl, - proxyUrl, - usingProxy, - proxyType, - keyLength: supabaseKey.length, - browserInfo: navigator.userAgent, - timestamp: new Date().toISOString(), - backupProxySuccess: false, // 백업 프록시 성공 여부 - lastErrorDetails: '' // 마지막 오류 상세 정보 - } - }; - - console.log('연결 테스트 시작 - 설정 정보:', { - originalUrl, - proxyUrl, - usingProxy, - proxyType - }); - - try { - // 1. REST API 접근 테스트 - 다양한 URL 형식 시도 - try { - console.log('REST API 테스트 시작...'); - - // 여러 형태의 REST API 엔드포인트 URL 구성 시도 - let apiUrl = ''; - let response = null; - let errorBody = ''; - - // 1번째 시도: 기본 URL + /rest/v1/ - apiUrl = proxyUrl.endsWith('/') - ? `${proxyUrl}rest/v1/` - : `${proxyUrl}/rest/v1/`; - - console.log('REST API 테스트 URL (시도 1):', apiUrl); - - try { - response = await fetch(apiUrl, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': supabaseKey, - }, - }); - - if (response.ok) { - results.restApi = true; - console.log('REST API 테스트 성공 (시도 1)'); - } else { - errorBody = await response.text(); - console.warn(`REST API 테스트 실패 (시도 1) - 상태: ${response.status}, 오류: ${errorBody}`); - results.debugInfo.lastErrorDetails = `상태 코드: ${response.status}, 응답: ${errorBody}`; - - // 2번째 시도: 다른 프록시 서비스 URL 직접 구성 - if (usingProxy) { - // 서로 다른 프록시 서비스 시도 - const proxyOptions = [ - { name: 'thingproxy', url: `https://thingproxy.freeboard.io/fetch/${originalUrl}/rest/v1/` }, - { name: 'allorigins', url: `https://api.allorigins.win/raw?url=${encodeURIComponent(`${originalUrl}/rest/v1/`)}` }, - { name: 'cors-anywhere', url: `https://cors-anywhere.herokuapp.com/${originalUrl}/rest/v1/` } - ]; - - // 현재 사용 중인 프록시와 다른 프록시만 시도 - const alternateProxies = proxyOptions.filter(p => p.name !== proxyType); - - for (const proxy of alternateProxies) { - console.log(`REST API 테스트 URL (시도 2 - ${proxy.name}):`, proxy.url); - - try { - response = await fetch(proxy.url, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': supabaseKey, - }, - }); - - if (response.ok) { - results.restApi = true; - results.debugInfo.backupProxySuccess = true; - console.log(`REST API 테스트 성공 (시도 2 - ${proxy.name})`); - results.errors.push(`REST API 성공: ${proxy.name} 프록시 사용 시 정상 작동합니다. 설정에서 이 프록시를 선택해보세요.`); - break; - } else { - const error2 = await response.text(); - console.warn(`REST API 테스트 실패 (시도 2 - ${proxy.name}) - 상태: ${response.status}, 오류: ${error2}`); - } - } catch (innerErr: any) { - console.error(`REST API 테스트 시도 2 (${proxy.name}) 예외:`, innerErr); - } - } - - if (!results.restApi) { - results.errors.push(`REST API 오류(${response.status}): ${errorBody || '응답 없음'} - 다른 프록시 옵션도 모두 실패했습니다.`); - } - } else { - results.errors.push(`REST API 오류(${response.status}): ${errorBody || '응답 없음'} - CORS 프록시 활성화를 시도해보세요.`); - } - } - } catch (outerErr: any) { - console.error('REST API 테스트 시도 1 예외:', outerErr); - results.errors.push(`REST API 예외 (시도 1): ${outerErr.message || '알 수 없는 오류'}`); - results.debugInfo.lastErrorDetails = outerErr.message || '알 수 없는 오류'; - - // 백업 시도 - if (usingProxy) { - try { - // 백업 프록시 시도: 다른 CORS 프록시 서비스 사용 - const backupProxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(`${originalUrl}/rest/v1/`)}`; - console.log('REST API 테스트 URL (백업 프록시):', backupProxyUrl); - - response = await fetch(backupProxyUrl, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - 'apikey': supabaseKey, - }, - }); - - if (response.ok) { - results.restApi = true; - console.log('REST API 테스트 성공 (백업 프록시)'); - results.debugInfo.backupProxySuccess = true; - results.errors.push('REST API 성공: allorigins 프록시 사용 시 정상 작동합니다. 설정에서 이 프록시를 선택해보세요.'); - } else { - const backupError = await response.text(); - console.warn(`REST API 테스트 실패 (백업 프록시) - 상태: ${response.status}, 오류: ${backupError}`); - } - } catch (backupErr: any) { - console.error('REST API 백업 프록시 예외:', backupErr); - } - } - } - } catch (err: any) { - results.errors.push(`REST API 예외: ${err.message || '알 수 없는 오류'}`); - console.error('REST API 테스트 중 예외:', err); - } - - // 2. 인증 서비스 테스트 - try { - console.log('인증 서비스 테스트 시작...'); - const { data, error } = await supabase.auth.getSession(); - results.auth = !error; - if (error) { - results.errors.push(`인증 오류: ${error.message}`); - console.error('인증 테스트 실패:', error); - } else { - console.log('인증 테스트 성공'); - } - } catch (err: any) { - results.errors.push(`인증 예외: ${err.message || '알 수 없는 오류'}`); - console.error('인증 테스트 중 예외:', err); - } - - // 3. 데이터베이스 연결 테스트 - try { - console.log('데이터베이스 연결 테스트 시작...'); - const { data, error } = await supabase - .from('transactions') - .select('*') - .limit(1); - - results.database = !error; - if (error) { - let errorMsg = error.message; - - // 익명 인증 오류 처리 - if (errorMsg.includes('Auth session missing') || errorMsg.includes('JWT')) { - errorMsg += ' - 로그인이 필요하거나 권한 설정을 확인해주세요.'; - } - - results.errors.push(`데이터베이스 오류: ${errorMsg}`); - console.error('데이터베이스 테스트 실패:', error); - } else { - console.log('데이터베이스 테스트 성공', data); - } - } catch (err: any) { - results.errors.push(`데이터베이스 예외: ${err.message || '알 수 없는 오류'}`); - console.error('데이터베이스 테스트 중 예외:', err); - } - - // 오류가 없는 경우 메시지 추가 - if (results.errors.length === 0) { - results.errors.push('모든 테스트 통과! 연결 상태가 정상입니다.'); - } - } catch (err: any) { - results.errors.push(`테스트 실행 예외: ${err.message || '알 수 없는 오류'}`); - console.error('전체 테스트 실행 중 예외:', err); - } - - console.log('Supabase 연결 테스트 결과:', results); - return results; -}; diff --git a/src/lib/supabase/tests/apiTests.ts b/src/lib/supabase/tests/apiTests.ts new file mode 100644 index 0000000..1c7e2ca --- /dev/null +++ b/src/lib/supabase/tests/apiTests.ts @@ -0,0 +1,127 @@ + +import { getOriginalSupabaseUrl, getSupabaseKey } from '../config'; + +// REST API 테스트 +export const testRestApi = async (proxyUrl: string, originalUrl: string, supabaseKey: string, proxyType: string): Promise<{ + success: boolean; + error?: any; + backupProxySuccess?: boolean; + lastErrorDetails?: string; + recommendedProxy?: string; +}> => { + console.log('REST API 테스트 시작...'); + + let apiUrl = ''; + let response = null; + let errorBody = ''; + let backupProxySuccess = false; + let lastErrorDetails = ''; + let recommendedProxy = ''; + + // 1번째 시도: 기본 URL + /rest/v1/ + apiUrl = proxyUrl.endsWith('/') + ? `${proxyUrl}rest/v1/` + : `${proxyUrl}/rest/v1/`; + + console.log('REST API 테스트 URL (시도 1):', apiUrl); + + try { + response = await fetch(apiUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'apikey': supabaseKey, + }, + }); + + if (response.ok) { + console.log('REST API 테스트 성공 (시도 1)'); + return { success: true }; + } else { + errorBody = await response.text(); + console.warn(`REST API 테스트 실패 (시도 1) - 상태: ${response.status}, 오류: ${errorBody}`); + lastErrorDetails = `상태 코드: ${response.status}, 응답: ${errorBody}`; + + // 2번째 시도: 다른 프록시 서비스 URL 직접 구성 + const proxyOptions = [ + { name: 'thingproxy', url: `https://thingproxy.freeboard.io/fetch/${originalUrl}/rest/v1/` }, + { name: 'allorigins', url: `https://api.allorigins.win/raw?url=${encodeURIComponent(`${originalUrl}/rest/v1/`)}` }, + { name: 'cors-anywhere', url: `https://cors-anywhere.herokuapp.com/${originalUrl}/rest/v1/` } + ]; + + // 현재 사용 중인 프록시와 다른 프록시만 시도 + const alternateProxies = proxyOptions.filter(p => p.name !== proxyType); + + for (const proxy of alternateProxies) { + console.log(`REST API 테스트 URL (시도 2 - ${proxy.name}):`, proxy.url); + + try { + response = await fetch(proxy.url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'apikey': supabaseKey, + }, + }); + + if (response.ok) { + backupProxySuccess = true; + recommendedProxy = proxy.name; + console.log(`REST API 테스트 성공 (시도 2 - ${proxy.name})`); + return { + success: false, + backupProxySuccess: true, + recommendedProxy: proxy.name, + lastErrorDetails + }; + } else { + const error2 = await response.text(); + console.warn(`REST API 테스트 실패 (시도 2 - ${proxy.name}) - 상태: ${response.status}, 오류: ${error2}`); + } + } catch (innerErr: any) { + console.error(`REST API 테스트 시도 2 (${proxy.name}) 예외:`, innerErr); + } + } + } + } catch (outerErr: any) { + console.error('REST API 테스트 시도 1 예외:', outerErr); + lastErrorDetails = outerErr.message || '알 수 없는 오류'; + + // 백업 시도 + try { + // 백업 프록시 시도: 다른 CORS 프록시 서비스 사용 + const backupProxyUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent(`${originalUrl}/rest/v1/`)}`; + console.log('REST API 테스트 URL (백업 프록시):', backupProxyUrl); + + response = await fetch(backupProxyUrl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'apikey': supabaseKey, + }, + }); + + if (response.ok) { + console.log('REST API 테스트 성공 (백업 프록시)'); + return { + success: false, + backupProxySuccess: true, + recommendedProxy: 'allorigins', + lastErrorDetails + }; + } else { + const backupError = await response.text(); + console.warn(`REST API 테스트 실패 (백업 프록시) - 상태: ${response.status}, 오류: ${backupError}`); + } + } catch (backupErr: any) { + console.error('REST API 백업 프록시 예외:', backupErr); + } + } + + return { + success: false, + backupProxySuccess, + recommendedProxy, + lastErrorDetails + }; +}; diff --git a/src/lib/supabase/tests/authTests.ts b/src/lib/supabase/tests/authTests.ts new file mode 100644 index 0000000..1c988f5 --- /dev/null +++ b/src/lib/supabase/tests/authTests.ts @@ -0,0 +1,45 @@ + +import { supabase } from '../client'; +import { LoginTestResult } from './types'; + +// 테스트용 직접 로그인 함수 (디버깅 전용) +export const testSupabaseLogin = async (email: string, password: string): Promise => { + try { + console.log('테스트 로그인 시도:', email); + + const { data, error } = await supabase.auth.signInWithPassword({ + email, + password + }); + + if (error) { + console.error('테스트 로그인 오류:', error); + return { success: false, error }; + } + + console.log('테스트 로그인 성공:', data); + return { success: true, data }; + } catch (err) { + console.error('테스트 로그인 중 예외 발생:', err); + return { success: false, error: err }; + } +}; + +// 인증 서비스 테스트 +export const testAuthService = async (): Promise<{ success: boolean; error?: any }> => { + try { + console.log('인증 서비스 테스트 시작...'); + const { data, error } = await supabase.auth.getSession(); + + if (error) { + console.error('인증 테스트 실패:', error); + return { success: false, error }; + } + + console.log('인증 테스트 성공'); + return { success: true }; + } catch (err) { + console.error('인증 테스트 중 예외:', err); + return { success: false, error: err }; + } +}; diff --git a/src/lib/supabase/tests/databaseTests.ts b/src/lib/supabase/tests/databaseTests.ts new file mode 100644 index 0000000..61c97f2 --- /dev/null +++ b/src/lib/supabase/tests/databaseTests.ts @@ -0,0 +1,31 @@ + +import { supabase } from '../client'; + +// 데이터베이스 연결 테스트 +export const testDatabaseConnection = async (): Promise<{ success: boolean; error?: any }> => { + try { + console.log('데이터베이스 연결 테스트 시작...'); + const { data, error } = await supabase + .from('transactions') + .select('*') + .limit(1); + + if (error) { + let errorMsg = error.message; + + // 익명 인증 오류 처리 + if (errorMsg.includes('Auth session missing') || errorMsg.includes('JWT')) { + errorMsg += ' - 로그인이 필요하거나 권한 설정을 확인해주세요.'; + } + + console.error('데이터베이스 테스트 실패:', error); + return { success: false, error: { message: errorMsg } }; + } else { + console.log('데이터베이스 테스트 성공', data); + return { success: true }; + } + } catch (err) { + console.error('데이터베이스 테스트 중 예외:', err); + return { success: false, error: err }; + } +}; diff --git a/src/lib/supabase/tests/index.ts b/src/lib/supabase/tests/index.ts new file mode 100644 index 0000000..e669423 --- /dev/null +++ b/src/lib/supabase/tests/index.ts @@ -0,0 +1,108 @@ + +import { getSupabaseUrl, getSupabaseKey, getOriginalSupabaseUrl, isCorsProxyEnabled, getProxyType } from '../config'; +import { testAuthService } from './authTests'; +import { testRestApi } from './apiTests'; +import { testDatabaseConnection } from './databaseTests'; +import { ConnectionTestResult, LoginTestResult } from './types'; + +export { testSupabaseLogin } from './authTests'; + +// API 테스트 도우미 함수 +export const testSupabaseConnection = async (): Promise => { + const originalUrl = getOriginalSupabaseUrl(); + const proxyUrl = getSupabaseUrl(); + const usingProxy = isCorsProxyEnabled(); + const proxyType = getProxyType(); + const supabaseKey = getSupabaseKey(); + + const results: ConnectionTestResult = { + url: originalUrl, // 원본 URL + proxyUrl: proxyUrl, // 프록시 적용된 URL + usingProxy: usingProxy, // 프록시 사용 여부 + proxyType: proxyType, // 프록시 유형 + client: !!supabase, + restApi: false, + auth: false, + database: false, + errors: [] as string[], + debugInfo: { + originalUrl, + proxyUrl, + usingProxy, + proxyType, + keyLength: supabaseKey.length, + browserInfo: navigator.userAgent, + timestamp: new Date().toISOString(), + backupProxySuccess: false, + lastErrorDetails: '' + } + }; + + console.log('연결 테스트 시작 - 설정 정보:', { + originalUrl, + proxyUrl, + usingProxy, + proxyType + }); + + try { + // 1. REST API 테스트 + try { + const apiTestResult = await testRestApi(proxyUrl, originalUrl, supabaseKey, proxyType); + results.restApi = apiTestResult.success; + + if (!apiTestResult.success) { + results.debugInfo.lastErrorDetails = apiTestResult.lastErrorDetails || ''; + results.debugInfo.backupProxySuccess = !!apiTestResult.backupProxySuccess; + + if (apiTestResult.backupProxySuccess && apiTestResult.recommendedProxy) { + results.errors.push(`REST API 성공: ${apiTestResult.recommendedProxy} 프록시 사용 시 정상 작동합니다. 설정에서 이 프록시를 선택해보세요.`); + } else if (usingProxy) { + results.errors.push(`REST API 오류: ${apiTestResult.lastErrorDetails || '응답 없음'} - 다른 프록시 옵션도 모두 실패했습니다.`); + } else { + results.errors.push(`REST API 오류: ${apiTestResult.lastErrorDetails || '응답 없음'} - CORS 프록시 활성화를 시도해보세요.`); + } + } + } catch (err: any) { + results.errors.push(`REST API 예외: ${err.message || '알 수 없는 오류'}`); + console.error('REST API 테스트 중 예외:', err); + } + + // 2. 인증 서비스 테스트 + try { + const authTestResult = await testAuthService(); + results.auth = authTestResult.success; + + if (!authTestResult.success) { + results.errors.push(`인증 오류: ${authTestResult.error?.message || '알 수 없는 오류'}`); + } + } catch (err: any) { + results.errors.push(`인증 예외: ${err.message || '알 수 없는 오류'}`); + console.error('인증 테스트 중 예외:', err); + } + + // 3. 데이터베이스 연결 테스트 + try { + const dbTestResult = await testDatabaseConnection(); + results.database = dbTestResult.success; + + if (!dbTestResult.success) { + results.errors.push(`데이터베이스 오류: ${dbTestResult.error?.message || '알 수 없는 오류'}`); + } + } catch (err: any) { + results.errors.push(`데이터베이스 예외: ${err.message || '알 수 없는 오류'}`); + console.error('데이터베이스 테스트 중 예외:', err); + } + + // 오류가 없는 경우 메시지 추가 + if (results.errors.length === 0) { + results.errors.push('모든 테스트 통과! 연결 상태가 정상입니다.'); + } + } catch (err: any) { + results.errors.push(`테스트 실행 예외: ${err.message || '알 수 없는 오류'}`); + console.error('전체 테스트 실행 중 예외:', err); + } + + console.log('Supabase 연결 테스트 결과:', results); + return results; +}; diff --git a/src/lib/supabase/tests/types.ts b/src/lib/supabase/tests/types.ts new file mode 100644 index 0000000..63b6ff1 --- /dev/null +++ b/src/lib/supabase/tests/types.ts @@ -0,0 +1,33 @@ + +// 테스트 결과를 위한 공통 타입 정의 + +export interface TestDebugInfo { + originalUrl: string; + proxyUrl: string; + usingProxy: boolean; + proxyType: string; + keyLength: number; + browserInfo: string; + timestamp: string; + backupProxySuccess: boolean; + lastErrorDetails: string; +} + +export interface ConnectionTestResult { + url: string; + proxyUrl: string; + usingProxy: boolean; + proxyType: string; + client: boolean; + restApi: boolean; + auth: boolean; + database: boolean; + errors: string[]; + debugInfo: TestDebugInfo; +} + +export interface LoginTestResult { + success: boolean; + data?: any; + error?: any; +}