From 893e1cf0aa5c0060d149440b8dd77e209b766cad 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:17:50 +0000 Subject: [PATCH] Improve Supabase connection testing Enhance connection testing to provide more detailed error information. --- src/lib/supabase/config.ts | 32 ++++++++- src/lib/supabase/tests.ts | 19 +++-- src/pages/Login.tsx | 20 +++++- src/pages/SupabaseSettings.tsx | 128 ++++++++++++++++++++++++++++++++- 4 files changed, 181 insertions(+), 18 deletions(-) diff --git a/src/lib/supabase/config.ts b/src/lib/supabase/config.ts index c2c1ac6..aedbf15 100644 --- a/src/lib/supabase/config.ts +++ b/src/lib/supabase/config.ts @@ -3,10 +3,19 @@ export const getSupabaseUrl = () => { // 로컬 스토리지에서 설정된 URL을 우선 사용 const storedUrl = localStorage.getItem('supabase_url'); - if (storedUrl) return storedUrl; + if (storedUrl) { + // CORS 프록시 설정 확인 + const useProxy = localStorage.getItem('use_cors_proxy') === 'true'; + if (useProxy && storedUrl.startsWith('http://')) { + // CORS 프록시 URL로 변환 + return `https://corsproxy.io/?${encodeURIComponent(storedUrl)}`; + } + return storedUrl; + } // 환경 변수 또는 기본값 사용 - return process.env.SUPABASE_URL || 'http://a11.ism.kr:8000'; + const defaultUrl = process.env.SUPABASE_URL || 'http://a11.ism.kr:8000'; + return defaultUrl; }; export const getSupabaseKey = () => { @@ -18,12 +27,29 @@ export const getSupabaseKey = () => { return process.env.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzQyMDM5MzU4LCJleHAiOjQ4OTU2MzkzNTh9.XK0vetdwv_H2MHj4ewTfZGtSbrbSNDaV5xJhNo_Hdp8'; }; +// CORS 프록시 사용 여부 설정 +export const useCorsProxy = (enabled: boolean) => { + localStorage.setItem('use_cors_proxy', enabled.toString()); +}; + +// CORS 프록시 사용 여부 확인 +export const isCorsProxyEnabled = () => { + return localStorage.getItem('use_cors_proxy') === 'true'; +}; + // 온프레미스 연결을 위한 설정 도우미 함수 -export const configureSupabase = (url: string, key: string) => { +export const configureSupabase = (url: string, key: string, useProxy: boolean = false) => { // 로컬 스토리지에 설정 저장 localStorage.setItem('supabase_url', url); localStorage.setItem('supabase_key', key); + localStorage.setItem('use_cors_proxy', useProxy.toString()); // 페이지 새로고침 - 새로운 설정으로 Supabase 클라이언트 초기화 window.location.reload(); }; + +// 원본 URL 반환 (프록시 없는 URL) +export const getOriginalSupabaseUrl = () => { + const storedUrl = localStorage.getItem('supabase_url'); + return storedUrl || process.env.SUPABASE_URL || 'http://a11.ism.kr:8000'; +}; diff --git a/src/lib/supabase/tests.ts b/src/lib/supabase/tests.ts index a131655..d772fd7 100644 --- a/src/lib/supabase/tests.ts +++ b/src/lib/supabase/tests.ts @@ -1,5 +1,6 @@ import { supabase } from './client'; +import { getSupabaseUrl, getSupabaseKey, getOriginalSupabaseUrl, isCorsProxyEnabled } from './config'; // 테스트용 직접 로그인 함수 (디버깅 전용) export const testSupabaseLogin = async (email: string, password: string) => { @@ -27,7 +28,9 @@ export const testSupabaseLogin = async (email: string, password: string) => { // API 테스트 도우미 함수 export const testSupabaseConnection = async () => { const results = { - url: getSupabaseUrl(), + url: getOriginalSupabaseUrl(), // 원본 URL + proxyUrl: getSupabaseUrl(), // 프록시 적용된 URL + usingProxy: isCorsProxyEnabled(), // 프록시 사용 여부 client: !!supabase, restApi: false, auth: false, @@ -39,7 +42,10 @@ export const testSupabaseConnection = async () => { // 1. REST API 접근 테스트 try { console.log('REST API 테스트 시작...'); - const response = await fetch(`${results.url}/rest/v1/`, { + const apiUrl = `${results.proxyUrl}/rest/v1/`; + console.log('REST API 테스트 URL:', apiUrl); + + const response = await fetch(apiUrl, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -108,12 +114,3 @@ export const testSupabaseConnection = async () => { console.log('Supabase 연결 테스트 결과:', results); return results; }; - -// 필요한 함수 불러오기 -function getSupabaseUrl() { - return localStorage.getItem('supabase_url') || process.env.SUPABASE_URL || 'http://a11.ism.kr:8000'; -} - -function getSupabaseKey() { - return localStorage.getItem('supabase_key') || process.env.SUPABASE_ANON_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzQyMDM5MzU4LCJleHAiOjQ4OTU2MzkzNTh9.XK0vetdwv_H2MHj4ewTfZGtSbrbSNDaV5xJhNo_Hdp8'; -} diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index e485639..7a5226a 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -4,7 +4,7 @@ import { Link, useNavigate } from "react-router-dom"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; -import { ArrowRight, Mail, KeyRound, Eye, EyeOff, RefreshCw } from "lucide-react"; +import { ArrowRight, Mail, KeyRound, Eye, EyeOff, RefreshCw, Shield } from "lucide-react"; import { useToast } from "@/hooks/useToast.wrapper"; import { useAuth } from "@/contexts/auth"; import { testSupabaseConnection } from "@/lib/supabase"; @@ -228,6 +228,15 @@ const Login = () => {

Supabase URL:

{testResults?.url || '알 수 없음'}

+ {testResults?.usingProxy && ( +
+

CORS 프록시:

+
+ +

활성화됨 - {testResults.proxyUrl}

+
+
+ )}

클라이언트 초기화:

{testResults?.client ? '성공' : '실패'}

@@ -247,6 +256,15 @@ const Login = () => {

데이터베이스: {testResults.database ? '✅' : '❌'}

)} +
+ + Supabase 설정 변경 + + +
diff --git a/src/pages/SupabaseSettings.tsx b/src/pages/SupabaseSettings.tsx index a561355..38c3b35 100644 --- a/src/pages/SupabaseSettings.tsx +++ b/src/pages/SupabaseSettings.tsx @@ -3,23 +3,30 @@ import React, { useState, useEffect } from 'react'; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; -import { DatabaseIcon, Save, RefreshCw } from "lucide-react"; +import { DatabaseIcon, Save, RefreshCw, Shield } from "lucide-react"; import { toast } from "@/hooks/useToast.wrapper"; -import { configureSupabase } from "@/lib/supabase"; +import { configureSupabase, isCorsProxyEnabled } from "@/lib/supabase/config"; +import { Switch } from "@/components/ui/switch"; +import { testSupabaseConnection } from "@/lib/supabase"; import NavBar from '@/components/NavBar'; const SupabaseSettings = () => { const [supabaseUrl, setSupabaseUrl] = useState(''); const [supabaseKey, setSupabaseKey] = useState(''); + const [useProxy, setUseProxy] = useState(false); const [isSaving, setIsSaving] = useState(false); + const [testResults, setTestResults] = useState(null); + const [isTesting, setIsTesting] = useState(false); // 저장된 설정 불러오기 useEffect(() => { const savedUrl = localStorage.getItem('supabase_url'); const savedKey = localStorage.getItem('supabase_key'); + const proxyEnabled = isCorsProxyEnabled(); if (savedUrl) setSupabaseUrl(savedUrl); if (savedKey) setSupabaseKey(savedKey); + setUseProxy(proxyEnabled); }, []); const handleSave = () => { @@ -36,7 +43,7 @@ const SupabaseSettings = () => { try { // Supabase 설정 적용 - configureSupabase(supabaseUrl, supabaseKey); + configureSupabase(supabaseUrl, supabaseKey, useProxy); toast({ title: "설정 저장 완료", @@ -53,6 +60,36 @@ const SupabaseSettings = () => { } }; + const runConnectionTest = async () => { + setIsTesting(true); + try { + const results = await testSupabaseConnection(); + setTestResults(results); + + if (results.errors.length === 0 || (results.auth && results.restApi && results.database)) { + toast({ + title: "연결 테스트 성공", + description: "Supabase 서버 연결이 정상입니다.", + }); + } else { + toast({ + title: "연결 테스트 실패", + description: `오류 발생: ${results.errors[0]}`, + variant: "destructive" + }); + } + } catch (error: any) { + console.error("연결 테스트 중 오류:", error); + toast({ + title: "연결 테스트 오류", + description: "테스트 실행 중 예상치 못한 오류가 발생했습니다.", + variant: "destructive" + }); + } finally { + setIsTesting(false); + } + }; + return (
@@ -101,6 +138,27 @@ const SupabaseSettings = () => {
+ {/* CORS 프록시 설정 추가 */} +
+
+ +
+ +
+ + + {testResults && ( +
+
+ REST API: + + {testResults.restApi ? '✅ 성공' : '❌ 실패'} + +
+
+ 인증: + + {testResults.auth ? '✅ 성공' : '❌ 실패'} + +
+
+ 데이터베이스: + + {testResults.database ? '✅ 성공' : '❌ 실패'} + +
+ + {testResults.usingProxy && ( +
+

CORS 프록시 사용 중: {testResults.proxyUrl}

+
+ )} + + {testResults.errors.length > 0 && ( +
+ {testResults.errors.map((error: string, index: number) => ( +

{error}

+ ))} +
+ )} +
+ )} + +

도움말

@@ -134,6 +253,9 @@ const SupabaseSettings = () => {

  • Anon Key: Supabase 대시보드의 API 설정에서 찾을 수 있는 anon/public 키를 입력합니다.
  • +
  • + CORS 프록시: HTTP URL에 대한 브라우저 보안 제한을 우회하기 위해 사용합니다. HTTPS가 아닌 URL에 접근 문제가 있는 경우 활성화하세요. +