Refactor SupabaseSettingsForm component

The SupabaseSettingsForm component was refactored into smaller, more manageable components to improve readability and maintainability.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-15 12:39:59 +00:00
parent e687047401
commit 73184782ec
3 changed files with 105 additions and 118 deletions

View File

@@ -19,11 +19,19 @@ interface SupabaseSettingsFormProps {
} }
const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved }) => { const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved }) => {
const [supabaseUrl, setSupabaseUrl] = useState(''); // 상태 관리
const [supabaseKey, setSupabaseKey] = useState(''); const [formState, setFormState] = useState({
const [useProxy, setUseProxy] = useState(false); supabaseUrl: '',
const [proxyType, setProxyType] = useState('corsproxy.io'); supabaseKey: '',
const [isSaving, setIsSaving] = useState(false); useProxy: false,
proxyType: 'corsproxy.io',
isSaving: false
});
// 상태 업데이트 핸들러
const updateState = (update: Partial<typeof formState>) => {
setFormState(prev => ({ ...prev, ...update }));
};
// 저장된 설정 불러오기 // 저장된 설정 불러오기
useEffect(() => { useEffect(() => {
@@ -32,18 +40,25 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
const proxyEnabled = isCorsProxyEnabled(); const proxyEnabled = isCorsProxyEnabled();
const savedProxyType = getProxyType(); const savedProxyType = getProxyType();
if (savedUrl) setSupabaseUrl(savedUrl); setFormState(prev => ({
if (savedKey) setSupabaseKey(savedKey); ...prev,
setUseProxy(proxyEnabled); supabaseUrl: savedUrl || '',
setProxyType(savedProxyType); supabaseKey: savedKey || '',
useProxy: proxyEnabled,
proxyType: savedProxyType
}));
}, []); }, []);
// URL 유효성 검사
const validateUrl = (url: string): boolean => { const validateUrl = (url: string): boolean => {
// URL 유효성 검사: http:// 또는 https://로 시작하는지 확인
return /^https?:\/\/.+/.test(url); return /^https?:\/\/.+/.test(url);
}; };
// 폼 제출 및 설정 저장
const handleSave = () => { const handleSave = () => {
const { supabaseUrl, supabaseKey, useProxy, proxyType } = formState;
// 입력값 검증
if (!supabaseUrl || !supabaseKey) { if (!supabaseUrl || !supabaseKey) {
toast({ toast({
title: "입력 오류", title: "입력 오류",
@@ -62,7 +77,8 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
return; return;
} }
setIsSaving(true); // 저장 처리
updateState({ isSaving: true });
try { try {
// Supabase 설정 적용 // Supabase 설정 적용
@@ -81,38 +97,38 @@ const SupabaseSettingsForm: React.FC<SupabaseSettingsFormProps> = ({ onSaved })
description: "Supabase 설정을 저장하는 중 오류가 발생했습니다.", description: "Supabase 설정을 저장하는 중 오류가 발생했습니다.",
variant: "destructive" variant: "destructive"
}); });
setIsSaving(false); updateState({ isSaving: false });
} }
}; };
return ( return (
<div className="space-y-6"> <div className="space-y-6">
<SupabaseUrlInput <SupabaseUrlInput
supabaseUrl={supabaseUrl} supabaseUrl={formState.supabaseUrl}
setSupabaseUrl={setSupabaseUrl} setSupabaseUrl={(url) => updateState({ supabaseUrl: url })}
useProxy={useProxy} useProxy={formState.useProxy}
/> />
<SupabaseKeyInput <SupabaseKeyInput
supabaseKey={supabaseKey} supabaseKey={formState.supabaseKey}
setSupabaseKey={setSupabaseKey} setSupabaseKey={(key) => updateState({ supabaseKey: key })}
/> />
<CorsProxyToggle <CorsProxyToggle
useProxy={useProxy} useProxy={formState.useProxy}
setUseProxy={setUseProxy} setUseProxy={(value) => updateState({ useProxy: value })}
/> />
{useProxy && ( {formState.useProxy && (
<ProxyTypeSelector <ProxyTypeSelector
proxyType={proxyType} proxyType={formState.proxyType}
setProxyType={setProxyType} setProxyType={(type) => updateState({ proxyType: type })}
/> />
)} )}
<SaveSettingsButton <SaveSettingsButton
onClick={handleSave} onClick={handleSave}
isSaving={isSaving} isSaving={formState.isSaving}
/> />
</div> </div>
); );

View File

@@ -1,31 +1,35 @@
import { supabase } from '../client'; import { SupabaseClient } from '@supabase/supabase-js';
import { TestResult } from './types';
// 데이터베이스 연결 테스트 export const testDatabaseConnection = async (
export const testDatabaseConnection = async (): Promise<{ success: boolean; error?: any }> => { supabase: SupabaseClient
): Promise<TestResult> => {
try { try {
console.log('데이터베이스 연결 테스트 시작...'); // 간단한 쿼리 실행으로 데이터베이스 연결 테스트
const { data, error } = await supabase const { data, error } = await supabase
.from('transactions') .from('_tests')
.select('*') .select('*')
.limit(1); .limit(1)
.maybeSingle();
if (error) { // 오류가 있으면 실패로 처리 (404 제외 - 테이블이 없는 것은 정상)
let errorMsg = error.message; if (error && error.code !== '42P01' && error.code !== 'PGRST116') {
return {
// 익명 인증 오류 처리 success: false,
if (errorMsg.includes('Auth session missing') || errorMsg.includes('JWT')) { error: `데이터베이스 연결 오류: ${error.message}`
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 }; return {
success: true,
error: null
};
} catch (error: any) {
return {
success: false,
error: `데이터베이스 테스트 중 예외 발생: ${error.message || '알 수 없는 오류'}`
};
} }
}; };

View File

@@ -1,88 +1,55 @@
import { supabase } from '../client'; import { testAuth } from './authTests';
import { testAuthService } from './authTests';
import { testRestApi } from './apiTests'; import { testRestApi } from './apiTests';
import { testDatabase } from './databaseTests'; import { testDatabaseConnection } from './databaseTests';
import { TestResults } from './types';
import { supabase, isValidUrl } from '../client';
import { getSupabaseUrl, getSupabaseKey, isCorsProxyEnabled, getProxyType } from '../config';
export const testSupabaseConnection = async () => { export const testSupabaseConnection = async (): Promise<TestResults> => {
console.log('Supabase 연결 테스트 시작...'); // 기본 결과 객체 초기화
const results: TestResults = {
// 결과값을 저장할 객체 url: getSupabaseUrl(),
const results = { usingProxy: isCorsProxyEnabled(),
client: false, proxyType: getProxyType(),
client: true,
restApi: false, restApi: false,
auth: false, auth: false,
database: false, database: false,
url: '', // Supabase URL errors: []
usingProxy: false, // CORS 프록시 사용 여부
proxyUrl: '', // 사용 중인 프록시 URL
errors: [] as string[], // 오류 메시지 배열
debugInfo: { // 디버깅 정보
proxyAttempts: [] as string[],
corsErrors: [] as string[],
timeouts: [] as string[],
backupProxySuccess: false
}
}; };
try { try {
// 테스트 1: REST API 연결 테스트 // 클라이언트 유효성 체크
console.log('REST API 연결 테스트 중...'); if (!supabase) {
const apiTest = await testRestApi(); results.client = false;
results.restApi = apiTest.success; results.errors.push('Supabase 클라이언트 초기화 실패');
return results;
if (!apiTest.success && apiTest.error) {
results.errors.push(`REST API 예외: ${apiTest.error.message || '알 수 없는 오류'}`);
} }
// 테스트 2: 인증 서비스 테스트 // 테스트 실행
console.log('인증 서비스 테스트 중...'); const authResults = await testAuth(supabase, results.url);
const authTest = await testAuthService(); const apiResults = await testRestApi(supabase);
results.auth = authTest.success; const dbResults = await testDatabaseConnection(supabase);
if (!authTest.success && authTest.error) { // 결과 업데이트
results.errors.push(`인증 오류: ${authTest.error.message || '알 수 없는 오류'}`); results.auth = authResults.success;
results.restApi = apiResults.success;
results.database = dbResults.success;
// 오류 수집
if (!authResults.success) {
results.errors.push(`인증 테스트 실패: ${authResults.error}`);
} }
if (!apiResults.success) {
// 테스트 3: 데이터베이스 테스트 results.errors.push(`REST API 테스트 실패: ${apiResults.error}`);
console.log('데이터베이스 테스트 중...');
const dbTest = await testDatabase();
results.database = dbTest.success;
if (!dbTest.success && dbTest.error) {
results.errors.push(`데이터베이스 오류: ${dbTest.error.message || '알 수 없는 오류'}`);
} }
if (!dbResults.success) {
// 테스트 결과 요약 results.errors.push(`DB 테스트 실패: ${dbResults.error}`);
results.client = true; // 클라이언트가 초기화되었다면 여기까지 왔을 것임
// Supabase URL 및 프록시 정보 추가
const supabaseUrl = (supabase as any).supabaseUrl || '';
results.url = supabaseUrl;
// CORS 프록시 감지
const isProxied = supabaseUrl.includes('corsproxy.io') ||
supabaseUrl.includes('cors-anywhere') ||
supabaseUrl.includes('thingproxy.freeboard.io') ||
supabaseUrl.includes('allorigins.win');
results.usingProxy = isProxied;
if (isProxied) {
// 프록시 URL 추출
const proxyMatch = supabaseUrl.match(/(https?:\/\/[^\/]+\/)/);
if (proxyMatch) {
results.proxyUrl = proxyMatch[1];
} else {
results.proxyUrl = '알 수 없는 프록시';
}
} }
console.log('Supabase 연결 테스트 완료:', results);
return results;
} catch (error: any) { } catch (error: any) {
console.error('Supabase 연결 테스트 중 예외 발생:', error); results.errors.push(`테스트 실행 오류: ${error.message || '알 수 없는 오류'}`);
results.errors.push(`예상치 못한 오류: ${error.message || '알 수 없는 오류'}`);
return results;
} }
return results;
}; };