diff --git a/src/components/supabase/ConnectionTestButton.tsx b/src/components/supabase/ConnectionTestButton.tsx new file mode 100644 index 0000000..41564cf --- /dev/null +++ b/src/components/supabase/ConnectionTestButton.tsx @@ -0,0 +1,34 @@ + +import React from 'react'; +import { Button } from "@/components/ui/button"; +import { RefreshCw } from "lucide-react"; + +interface ConnectionTestButtonProps { + onClick: () => void; + isTesting: boolean; +} + +const ConnectionTestButton: React.FC = ({ onClick, isTesting }) => { + return ( + + ); +}; + +export default ConnectionTestButton; diff --git a/src/components/supabase/DebugInfoCollapsible.tsx b/src/components/supabase/DebugInfoCollapsible.tsx new file mode 100644 index 0000000..35fadbc --- /dev/null +++ b/src/components/supabase/DebugInfoCollapsible.tsx @@ -0,0 +1,99 @@ + +import React from 'react'; +import { Info } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { TestResults } from '@/lib/supabase/tests/types'; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger +} from "@/components/ui/collapsible"; + +interface DebugInfoCollapsibleProps { + testResults: TestResults; + showDebug: boolean; + setShowDebug: (show: boolean) => void; +} + +const DebugInfoCollapsible: React.FC = ({ + testResults, + showDebug, + setShowDebug +}) => { + if (!testResults.debugInfo) return null; + + return ( + +
+

고급 진단 정보

+ + + +
+ + +
+
+ Supabase URL: +
+ {testResults.url} +
+
+ + {testResults.usingProxy && ( +
+ 프록시 URL: +
+ {testResults.proxyUrl} +
+
+ 프록시 유형: {testResults.proxyType || 'corsproxy.io'} +
+
+ )} + +
+ 클라이언트 초기화: +
+ {testResults.client ? '성공' : '실패'} +
+
+ + {testResults.debugInfo.lastErrorDetails && ( +
+ 마지막 오류 상세: +
+ {testResults.debugInfo.lastErrorDetails} +
+
+ )} + +
+ 브라우저 정보: +
+ {testResults.debugInfo.browserInfo} +
+
+ +
+ 테스트 시간: +
+ {new Date(testResults.debugInfo.timestamp).toLocaleString()} +
+
+
+
+
+ ); +}; + +export default DebugInfoCollapsible; diff --git a/src/components/supabase/ErrorMessageCard.tsx b/src/components/supabase/ErrorMessageCard.tsx new file mode 100644 index 0000000..fae7a85 --- /dev/null +++ b/src/components/supabase/ErrorMessageCard.tsx @@ -0,0 +1,20 @@ + +import React from 'react'; + +interface ErrorMessageCardProps { + errors: string[]; +} + +const ErrorMessageCard: React.FC = ({ errors }) => { + if (errors.length === 0) return null; + + return ( +
+ {errors.map((error: string, index: number) => ( +

{error}

+ ))} +
+ ); +}; + +export default ErrorMessageCard; diff --git a/src/components/supabase/ProxyInfoCard.tsx b/src/components/supabase/ProxyInfoCard.tsx new file mode 100644 index 0000000..41e1377 --- /dev/null +++ b/src/components/supabase/ProxyInfoCard.tsx @@ -0,0 +1,20 @@ + +import React from 'react'; +import { TestResults } from '@/lib/supabase/tests/types'; + +interface ProxyInfoCardProps { + testResults: TestResults; +} + +const ProxyInfoCard: React.FC = ({ testResults }) => { + if (!testResults.usingProxy) return null; + + return ( +
+

CORS 프록시 사용 중: {testResults.proxyType || 'corsproxy.io'}

+

{testResults.proxyUrl}

+
+ ); +}; + +export default ProxyInfoCard; diff --git a/src/components/supabase/ProxyRecommendationAlert.tsx b/src/components/supabase/ProxyRecommendationAlert.tsx new file mode 100644 index 0000000..383c174 --- /dev/null +++ b/src/components/supabase/ProxyRecommendationAlert.tsx @@ -0,0 +1,34 @@ + +import React from 'react'; +import { AlertCircle } from "lucide-react"; +import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"; + +interface ProxyRecommendationAlertProps { + errors: string[]; +} + +const ProxyRecommendationAlert: React.FC = ({ errors }) => { + const hasProxyRecommendation = errors.some(err => + err.includes('프록시 사용 시 정상 작동합니다') || + err.includes('프록시를 선택해보세요') + ); + + if (!hasProxyRecommendation || errors.length === 0) return null; + + const recommendationMessage = errors.find(err => + err.includes('프록시 사용 시 정상 작동합니다') || + err.includes('프록시를 선택해보세요') + ); + + return ( + + + 프록시 변경 권장 + + {recommendationMessage} + + + ); +}; + +export default ProxyRecommendationAlert; diff --git a/src/components/supabase/SupabaseConnectionTest.tsx b/src/components/supabase/SupabaseConnectionTest.tsx index 41626ff..cc8f06a 100644 --- a/src/components/supabase/SupabaseConnectionTest.tsx +++ b/src/components/supabase/SupabaseConnectionTest.tsx @@ -1,12 +1,18 @@ + import React, { useState } from 'react'; -import { Button } from "@/components/ui/button"; -import { RefreshCw, Info, HelpCircle, AlertCircle } from "lucide-react"; import { toast } from "@/hooks/useToast.wrapper"; import { testSupabaseConnection } from '@/lib/supabase'; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; -import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"; import { TestResults } from '@/lib/supabase/tests/types'; +// 분리된 컴포넌트들 임포트 +import ConnectionTestButton from './ConnectionTestButton'; +import TestResultItem from './TestResultItem'; +import ProxyInfoCard from './ProxyInfoCard'; +import ProxyRecommendationAlert from './ProxyRecommendationAlert'; +import ErrorMessageCard from './ErrorMessageCard'; +import TroubleshootingTips from './TroubleshootingTips'; +import DebugInfoCollapsible from './DebugInfoCollapsible'; + const SupabaseConnectionTest: React.FC = () => { const [testResults, setTestResults] = useState(null); const [isTesting, setIsTesting] = useState(false); @@ -42,175 +48,34 @@ const SupabaseConnectionTest: React.FC = () => { } }; - const hasProxyRecommendation = (errors: string[]) => { - return errors.some(err => - err.includes('프록시 사용 시 정상 작동합니다') || - err.includes('프록시를 선택해보세요') - ); - }; - return (

연결 테스트

- + {testResults && (
-
- REST API: - - {testResults.restApi ? '✅ 성공' : '❌ 실패'} - -
-
- 인증: - - {testResults.auth ? '✅ 성공' : '❌ 실패'} - -
-
- 데이터베이스: - - {testResults.database ? '✅ 성공' : '❌ 실패'} - -
+ + + - {testResults.usingProxy && ( -
-

CORS 프록시 사용 중: {testResults.proxyType || 'corsproxy.io'}

-

{testResults.proxyUrl}

-
- )} + - {testResults.errors.length > 0 && hasProxyRecommendation(testResults.errors) && ( - - - 프록시 변경 권장 - - {testResults.errors.find(err => - err.includes('프록시 사용 시 정상 작동합니다') || - err.includes('프록시를 선택해보세요') - )} - - - )} + - {testResults.errors.length > 0 && ( -
- {testResults.errors.map((error: string, index: number) => ( -

{error}

- ))} -
- )} + - {/* 오류 해결 팁 */} - {!testResults.restApi && testResults.auth && ( -
-
- -
-

인증은 성공했지만 API/DB 연결에 실패했습니다

-
    -
  • 다른 CORS 프록시 옵션을 시도해보세요
  • -
  • Supabase 서버의 CORS 설정을 확인하세요
  • -
  • 브라우저 개발자 도구에서 네트워크 탭을 확인하세요
  • -
-
-
-
- )} + - {/* 디버그 정보 섹션 추가 */} - {testResults.debugInfo && ( - -
-

고급 진단 정보

- - - -
- - -
-
- Supabase URL: -
- {testResults.url} -
-
- - {testResults.usingProxy && ( -
- 프록시 URL: -
- {testResults.proxyUrl} -
-
- 프록시 유형: {testResults.proxyType || 'corsproxy.io'} -
-
- )} - -
- 클라이언트 초기화: -
- {testResults.client ? '성공' : '실패'} -
-
- - {testResults.debugInfo.lastErrorDetails && ( -
- 마지막 오류 상세: -
- {testResults.debugInfo.lastErrorDetails} -
-
- )} - -
- 브라우저 정보: -
- {testResults.debugInfo.browserInfo} -
-
- -
- 테스트 시간: -
- {new Date(testResults.debugInfo.timestamp).toLocaleString()} -
-
-
-
-
- )} +
)}
diff --git a/src/components/supabase/TestResultItem.tsx b/src/components/supabase/TestResultItem.tsx new file mode 100644 index 0000000..45d1ef6 --- /dev/null +++ b/src/components/supabase/TestResultItem.tsx @@ -0,0 +1,20 @@ + +import React from 'react'; + +interface TestResultItemProps { + label: string; + success: boolean; +} + +const TestResultItem: React.FC = ({ label, success }) => { + return ( +
+ {label}: + + {success ? '✅ 성공' : '❌ 실패'} + +
+ ); +}; + +export default TestResultItem; diff --git a/src/components/supabase/TroubleshootingTips.tsx b/src/components/supabase/TroubleshootingTips.tsx new file mode 100644 index 0000000..ab9edd2 --- /dev/null +++ b/src/components/supabase/TroubleshootingTips.tsx @@ -0,0 +1,30 @@ + +import React from 'react'; +import { HelpCircle } from "lucide-react"; +import { TestResults } from '@/lib/supabase/tests/types'; + +interface TroubleshootingTipsProps { + testResults: TestResults; +} + +const TroubleshootingTips: React.FC = ({ testResults }) => { + if (!(!testResults.restApi && testResults.auth)) return null; + + return ( +
+
+ +
+

인증은 성공했지만 API/DB 연결에 실패했습니다

+
    +
  • 다른 CORS 프록시 옵션을 시도해보세요
  • +
  • Supabase 서버의 CORS 설정을 확인하세요
  • +
  • 브라우저 개발자 도구에서 네트워크 탭을 확인하세요
  • +
+
+
+
+ ); +}; + +export default TroubleshootingTips; diff --git a/src/lib/supabase/tests/index.ts b/src/lib/supabase/tests/index.ts index 3243415..4c6fa14 100644 --- a/src/lib/supabase/tests/index.ts +++ b/src/lib/supabase/tests/index.ts @@ -2,7 +2,7 @@ import { testAuth } from './authTests'; import { testRestApi } from './apiTests'; import { testDatabaseConnection } from './databaseTests'; -import { TestResults } from './types'; +import { TestResults, TestDebugInfo } from './types'; import { supabase, isValidUrl } from '../client'; import { getSupabaseUrl, getSupabaseKey, isCorsProxyEnabled, getProxyType } from '../config'; @@ -17,7 +17,18 @@ export const testSupabaseConnection = async (): Promise => { restApi: false, auth: false, database: false, - errors: [] + errors: [], + debugInfo: { + originalUrl: getSupabaseUrl(), + proxyUrl: '', + usingProxy: isCorsProxyEnabled(), + proxyType: getProxyType(), + keyLength: getSupabaseKey().length, + browserInfo: navigator.userAgent, + timestamp: new Date().toISOString(), + backupProxySuccess: false, + lastErrorDetails: '' + } }; try { @@ -40,12 +51,16 @@ export const testSupabaseConnection = async (): Promise => { } else { results.proxyUrl = baseUrl; // 기본값 } + + // debugInfo에도 proxyUrl 설정 + results.debugInfo.proxyUrl = results.proxyUrl; } else { results.proxyUrl = results.url; // 프록시 사용 안 함 + results.debugInfo.proxyUrl = results.url; } // 테스트 실행 - const authResults = await testAuth(supabase, results.url); + const authResults = await testAuth(supabase); const apiResults = await testRestApi(supabase); const dbResults = await testDatabaseConnection(supabase); @@ -57,15 +72,20 @@ export const testSupabaseConnection = async (): Promise => { // 오류 수집 if (!authResults.success && authResults.error) { results.errors.push(`인증 테스트 실패: ${authResults.error}`); + results.debugInfo.lastErrorDetails += `인증: ${authResults.error}; `; } if (!apiResults.success && apiResults.error) { results.errors.push(`REST API 테스트 실패: ${apiResults.error}`); + results.debugInfo.lastErrorDetails += `API: ${apiResults.error}; `; } if (!dbResults.success && dbResults.error) { results.errors.push(`DB 테스트 실패: ${dbResults.error}`); + results.debugInfo.lastErrorDetails += `DB: ${dbResults.error}; `; } } catch (error: any) { - results.errors.push(`테스트 실행 오류: ${error.message || '알 수 없는 오류'}`); + const errorMsg = `테스트 실행 오류: ${error.message || '알 수 없는 오류'}`; + results.errors.push(errorMsg); + results.debugInfo.lastErrorDetails = errorMsg; } return results; diff --git a/src/lib/supabase/tests/types.ts b/src/lib/supabase/tests/types.ts index d549d0f..40924f7 100644 --- a/src/lib/supabase/tests/types.ts +++ b/src/lib/supabase/tests/types.ts @@ -6,18 +6,6 @@ export interface TestResult { error: string | null; } -export interface TestResults { - url: string; - proxyUrl: string; // 추가된 필드 - usingProxy: boolean; - proxyType: string; - client: boolean; - restApi: boolean; - auth: boolean; - database: boolean; - errors: string[]; -} - export interface TestDebugInfo { originalUrl: string; proxyUrl: string; @@ -30,6 +18,19 @@ export interface TestDebugInfo { lastErrorDetails: string; } +export interface TestResults { + url: string; + proxyUrl: string; + usingProxy: boolean; + proxyType: string; + client: boolean; + restApi: boolean; + auth: boolean; + database: boolean; + errors: string[]; + debugInfo: TestDebugInfo; +} + export interface ConnectionTestResult { url: string; proxyUrl: string;