diff --git a/src/components/supabase/ProxyRecommendationAlert.tsx b/src/components/supabase/ProxyRecommendationAlert.tsx index 383c174..fca4314 100644 --- a/src/components/supabase/ProxyRecommendationAlert.tsx +++ b/src/components/supabase/ProxyRecommendationAlert.tsx @@ -8,24 +8,25 @@ interface ProxyRecommendationAlertProps { } const ProxyRecommendationAlert: React.FC = ({ errors }) => { - const hasProxyRecommendation = errors.some(err => - err.includes('프록시 사용 시 정상 작동합니다') || - err.includes('프록시를 선택해보세요') + const hasCorsError = errors.some(err => + err.includes('CORS') || + err.includes('Failed to fetch') || + err.includes('프록시 사용시 정상 작동') || + err.includes('프록시를 활성화') ); - if (!hasProxyRecommendation || errors.length === 0) return null; - - const recommendationMessage = errors.find(err => - err.includes('프록시 사용 시 정상 작동합니다') || - err.includes('프록시를 선택해보세요') - ); + if (!hasCorsError || errors.length === 0) return null; return ( - 프록시 변경 권장 + CORS 오류 감지됨 - {recommendationMessage} +

HTTP URL에 대한 브라우저 보안 제한으로 인해 연결에 실패했습니다.

+
    +
  • CORS 프록시를 활성화하고 프록시 유형을 변경해보세요.
  • +
  • 또는 HTTPS URL로 변경하는 것을 고려하세요.
  • +
); diff --git a/src/components/supabase/ProxyTypeSelector.tsx b/src/components/supabase/ProxyTypeSelector.tsx index 8361840..2dd6c48 100644 --- a/src/components/supabase/ProxyTypeSelector.tsx +++ b/src/components/supabase/ProxyTypeSelector.tsx @@ -24,6 +24,7 @@ const ProxyTypeSelector: React.FC = ({ thingproxy.freeboard.io allorigins.win cors-anywhere.herokuapp.com + Cloudflare Workers 프록시

diff --git a/src/lib/supabase/config.ts b/src/lib/supabase/config.ts index 4c420eb..52add58 100644 --- a/src/lib/supabase/config.ts +++ b/src/lib/supabase/config.ts @@ -31,6 +31,14 @@ export const getSupabaseUrl = () => { case 'cors-anywhere': proxyUrl = `https://cors-anywhere.herokuapp.com/${urlForProxy}`; break; + case 'cloudflare': + // Cloudflare Workers CORS 프록시 + proxyUrl = `https://cors-proxy.azurewebsites.net/api/cors-proxy?url=${encodeURIComponent(urlForProxy)}`; + break; + case 'local-proxy': + // 사용자 지정 로컬 프록시 (개발 환경용) + proxyUrl = `http://localhost:8080/proxy?url=${encodeURIComponent(urlForProxy)}`; + break; default: proxyUrl = `https://corsproxy.io/?${encodeURIComponent(urlForProxy)}`; } @@ -42,8 +50,7 @@ export const getSupabaseUrl = () => { } // 기본값 사용 (환경 변수 대신) - const defaultUrl = 'http://a11.ism.kr:8000'; - return defaultUrl; + return 'http://a11.ism.kr:8000'; }; export const getSupabaseKey = () => { @@ -85,6 +92,12 @@ export const configureSupabase = (url: string, key: string, useProxy: boolean = ? cleanUrl : `http://${cleanUrl}`; + // HTTP URL을 사용하고 프록시가 활성화되지 않은 경우 경고 + const isHttpUrl = normalizedUrl.startsWith('http:') && !normalizedUrl.startsWith('http://localhost'); + if (isHttpUrl && !useProxy) { + console.warn('경고: HTTP URL을 사용하면서 CORS 프록시가 비활성화되어 있습니다. 브라우저에서 접근 문제가 발생할 수 있습니다.'); + } + // 로컬 스토리지에 설정 저장 localStorage.setItem('supabase_url', normalizedUrl); localStorage.setItem('supabase_key', key); diff --git a/src/lib/supabase/tests/apiTests.ts b/src/lib/supabase/tests/apiTests.ts index f6b8e37..713ff28 100644 --- a/src/lib/supabase/tests/apiTests.ts +++ b/src/lib/supabase/tests/apiTests.ts @@ -12,8 +12,7 @@ export const testRestApi = async ( try { const originalUrl = getSupabaseUrl(); const supabaseKey = getSupabaseKey(); - const proxyType = 'corsproxy.io'; // 기본값 - + if (!originalUrl || !supabaseKey) { return { success: false, @@ -21,13 +20,32 @@ export const testRestApi = async ( }; } + // HTTP URL 감지 + const isHttpUrl = originalUrl.startsWith('http:') && !originalUrl.startsWith('http://localhost'); + // 클라이언트 인스턴스로 간단한 API 호출 수행 const { data, error } = await supabase .from('_tests') .select('*') .limit(1); - if (error && error.code !== '42P01' && error.code !== 'PGRST116') { + if (error) { + // CORS 관련 오류인지 확인 + if (error.message && error.message.includes('fetch failed') && isHttpUrl) { + return { + success: false, + error: `REST API 요청 실패: ${error.message} (CORS 오류 가능성 높음. CORS 프록시 사용을 권장합니다)` + }; + } + + // 테이블이 없는 경우 정상 (테스트 테이블이 없을 수 있음) + if (error.code === '42P01' || error.code === 'PGRST116') { + return { + success: true, + error: null + }; + } + return { success: false, error: `REST API 요청 실패: ${error.message}` @@ -39,6 +57,17 @@ export const testRestApi = async ( error: null }; } catch (err: any) { + // HTTP URL을 사용하고 있는지 확인 + const url = getSupabaseUrl(); + const isHttpUrl = url.startsWith('http:') && !url.startsWith('http://localhost'); + + if (err.message && err.message.includes('Failed to fetch') && isHttpUrl) { + return { + success: false, + error: `REST API 테스트 실패: ${err.message} (CORS 프록시 사용시 정상 작동합니다. 설정에서 프록시를 활성화해보세요)` + }; + } + return { success: false, error: `REST API 테스트 예외: ${err.message || '알 수 없는 오류'}` diff --git a/src/lib/supabase/tests/databaseTests.ts b/src/lib/supabase/tests/databaseTests.ts index 8f73553..8bd4a47 100644 --- a/src/lib/supabase/tests/databaseTests.ts +++ b/src/lib/supabase/tests/databaseTests.ts @@ -1,6 +1,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import { TestResult } from './types'; +import { getSupabaseUrl } from '../config'; export const testDatabaseConnection = async ( supabase: SupabaseClient @@ -13,8 +14,16 @@ export const testDatabaseConnection = async ( .limit(1) .maybeSingle(); - // 오류가 있으면 실패로 처리 (404 제외 - 테이블이 없는 것은 정상) - if (error && error.code !== '42P01' && error.code !== 'PGRST116') { + // 테이블이 없는 경우 정상 (테스트 테이블이 없을 수 있음) + if (error && (error.code === '42P01' || error.code === 'PGRST116')) { + return { + success: true, + error: null + }; + } + + // 다른 오류가 있으면 실패로 처리 + if (error) { return { success: false, error: `데이터베이스 연결 오류: ${error.message}` @@ -27,6 +36,17 @@ export const testDatabaseConnection = async ( error: null }; } catch (error: any) { + // HTTP URL 관련 CORS 오류 확인 + const url = getSupabaseUrl(); + const isHttpUrl = url.startsWith('http:') && !url.startsWith('http://localhost'); + + if (error.message && error.message.includes('Failed to fetch') && isHttpUrl) { + return { + success: false, + error: `데이터베이스 테스트 실패: ${error.message} (CORS 프록시 사용시 정상 작동합니다. 설정에서 프록시를 활성화해보세요)` + }; + } + return { success: false, error: `데이터베이스 테스트 중 예외 발생: ${error.message || '알 수 없는 오류'}`