Update error message
Update the error message displayed during sign-up.
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -49,17 +50,26 @@ const RegisterForm: React.FC<RegisterFormProps> = ({
|
|||||||
|
|
||||||
// 서버 연결 상태 재확인
|
// 서버 연결 상태 재확인
|
||||||
if (!serverStatus.connected) {
|
if (!serverStatus.connected) {
|
||||||
const currentStatus = await verifyServerConnection();
|
try {
|
||||||
setServerStatus({
|
const currentStatus = await verifyServerConnection();
|
||||||
checked: true,
|
setServerStatus({
|
||||||
connected: currentStatus.connected,
|
checked: true,
|
||||||
message: currentStatus.message
|
connected: currentStatus.connected,
|
||||||
});
|
message: currentStatus.message
|
||||||
|
});
|
||||||
if (!currentStatus.connected) {
|
|
||||||
|
if (!currentStatus.connected) {
|
||||||
|
toast({
|
||||||
|
title: "서버 연결 실패",
|
||||||
|
description: "서버에 연결할 수 없습니다. 네트워크 또는 서버 상태를 확인하세요.",
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
toast({
|
toast({
|
||||||
title: "서버 연결 실패",
|
title: "연결 확인 오류",
|
||||||
description: "서버에 연결할 수 없습니다. 네트워크 또는 서버 상태를 확인하세요.",
|
description: error.message || "서버 연결 확인 중 오류가 발생했습니다.",
|
||||||
variant: "destructive"
|
variant: "destructive"
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -84,20 +94,79 @@ const RegisterForm: React.FC<RegisterFormProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 비밀번호 강도 검사
|
||||||
|
if (password.length < 8) {
|
||||||
|
toast({
|
||||||
|
title: "비밀번호 강도 부족",
|
||||||
|
description: "비밀번호는 최소 8자 이상이어야 합니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이메일 형식 검사
|
||||||
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!emailPattern.test(email)) {
|
||||||
|
toast({
|
||||||
|
title: "이메일 형식 오류",
|
||||||
|
description: "유효한 이메일 주소를 입력해주세요.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 회원가입 시도
|
||||||
const { error, user } = await signUp(email, password, username);
|
const { error, user } = await signUp(email, password, username);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
// 오류 메시지 출력
|
||||||
setRegisterError(error.message || '알 수 없는 오류가 발생했습니다.');
|
setRegisterError(error.message || '알 수 없는 오류가 발생했습니다.');
|
||||||
|
|
||||||
|
// 네트워크 관련 오류인 경우 자세한 안내
|
||||||
|
if (error.message && (
|
||||||
|
error.message.includes('fetch') ||
|
||||||
|
error.message.includes('네트워크') ||
|
||||||
|
error.message.includes('CORS'))) {
|
||||||
|
toast({
|
||||||
|
title: "네트워크 오류",
|
||||||
|
description: "서버에 연결할 수 없습니다. 설정에서 CORS 프록시가 활성화되어 있는지 확인하세요.",
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 서버 응답 관련 오류인 경우
|
||||||
|
else if (error.message && (
|
||||||
|
error.message.includes('400') ||
|
||||||
|
error.message.includes('401') ||
|
||||||
|
error.message.includes('403') ||
|
||||||
|
error.message.includes('500'))) {
|
||||||
|
toast({
|
||||||
|
title: "서버 응답 오류",
|
||||||
|
description: error.message,
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (user) {
|
} else if (user) {
|
||||||
// 회원가입 성공 시 로그인 페이지로 이동
|
// 회원가입 성공
|
||||||
|
toast({
|
||||||
|
title: "회원가입 성공",
|
||||||
|
description: "회원가입이 완료되었습니다. 로그인 페이지로 이동합니다.",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 로그인 페이지로 이동
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("회원가입 처리 중 예외 발생:", error);
|
console.error("회원가입 처리 중 예외 발생:", error);
|
||||||
setRegisterError(error.message || '예상치 못한 오류가 발생했습니다.');
|
setRegisterError(error.message || '예상치 못한 오류가 발생했습니다.');
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: "회원가입 오류",
|
||||||
|
description: error.message || "회원가입 처리 중 오류가 발생했습니다.",
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@@ -157,6 +226,9 @@ const RegisterForm: React.FC<RegisterFormProps> = ({
|
|||||||
{showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />}
|
{showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{password && password.length > 0 && password.length < 8 && (
|
||||||
|
<p className="text-xs text-red-500 mt-1">비밀번호는 최소 8자 이상이어야 합니다.</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -172,6 +244,9 @@ const RegisterForm: React.FC<RegisterFormProps> = ({
|
|||||||
className="pl-10 neuro-pressed"
|
className="pl-10 neuro-pressed"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{confirmPassword && password !== confirmPassword && (
|
||||||
|
<p className="text-xs text-red-500 mt-1">비밀번호가 일치하지 않습니다.</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ export const signUp = async (email: string, password: string, username: string)
|
|||||||
options: {
|
options: {
|
||||||
data: {
|
data: {
|
||||||
username, // 사용자 이름을 메타데이터에 저장
|
username, // 사용자 이름을 메타데이터에 저장
|
||||||
}
|
},
|
||||||
|
emailRedirectTo: window.location.origin + '/login' // 이메일 인증 완료 후 리디렉션 URL
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,7 +35,8 @@ export const signUp = async (email: string, password: string, username: string)
|
|||||||
if (error.message.includes('json') ||
|
if (error.message.includes('json') ||
|
||||||
error.message.includes('Unexpected end') ||
|
error.message.includes('Unexpected end') ||
|
||||||
error.message.includes('404') ||
|
error.message.includes('404') ||
|
||||||
error.message.includes('Not Found')) {
|
error.message.includes('Not Found') ||
|
||||||
|
error.message.includes('Failed to fetch')) {
|
||||||
console.warn('기본 회원가입 실패, 직접 API 호출 시도:', error.message);
|
console.warn('기본 회원가입 실패, 직접 API 호출 시도:', error.message);
|
||||||
return await signUpWithDirectApi(email, password, username);
|
return await signUpWithDirectApi(email, password, username);
|
||||||
}
|
}
|
||||||
@@ -76,8 +78,12 @@ export const signUp = async (email: string, password: string, username: string)
|
|||||||
|
|
||||||
// 사용자 데이터가 없는 경우 (드물게 발생)
|
// 사용자 데이터가 없는 경우 (드물게 발생)
|
||||||
console.warn('회원가입 응답은 성공했지만 사용자 데이터가 없습니다');
|
console.warn('회원가입 응답은 성공했지만 사용자 데이터가 없습니다');
|
||||||
showAuthToast('회원가입 문제', '계정이 생성되었으나 응답에 사용자 정보가 없습니다.', 'destructive');
|
showAuthToast('회원가입 성공', '계정이 생성되었습니다. 로그인해주세요.', 'default');
|
||||||
return { error: { message: '회원가입 완료 처리 중 문제가 발생했습니다.' }, user: null };
|
return {
|
||||||
|
error: null,
|
||||||
|
user: { email },
|
||||||
|
message: '회원가입 완료'
|
||||||
|
};
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('기본 회원가입 프로세스 예외:', error);
|
console.error('기본 회원가입 프로세스 예외:', error);
|
||||||
|
|
||||||
@@ -86,7 +92,9 @@ export const signUp = async (email: string, password: string, username: string)
|
|||||||
error.message.includes('json') ||
|
error.message.includes('json') ||
|
||||||
error.message.includes('fetch') ||
|
error.message.includes('fetch') ||
|
||||||
error.message.includes('404') ||
|
error.message.includes('404') ||
|
||||||
error.message.includes('Not Found'))) {
|
error.message.includes('Not Found') ||
|
||||||
|
error.message.includes('timed out') ||
|
||||||
|
error.message.includes('Failed to fetch'))) {
|
||||||
console.warn('직접 API 호출로 재시도:', error);
|
console.warn('직접 API 호출로 재시도:', error);
|
||||||
return await signUpWithDirectApi(email, password, username);
|
return await signUpWithDirectApi(email, password, username);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
|
|||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
data: { username } // 사용자 메타데이터에 username 추가
|
data: { username } // 사용자 메타데이터에 username 추가
|
||||||
})
|
}),
|
||||||
|
signal: AbortSignal.timeout(15000) // 타임아웃 시간 증가
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('회원가입 응답 상태:', response.status);
|
console.log('회원가입 응답 상태:', response.status);
|
||||||
@@ -64,9 +65,20 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
|
|||||||
let responseData;
|
let responseData;
|
||||||
try {
|
try {
|
||||||
// 응답이 비어있지 않은 경우에만 JSON 파싱 시도
|
// 응답이 비어있지 않은 경우에만 JSON 파싱 시도
|
||||||
responseData = responseText ? JSON.parse(responseText) : {};
|
responseData = responseText && responseText.trim() !== '' ? JSON.parse(responseText) : {};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('JSON 파싱 실패:', e, '원본 응답:', responseText);
|
console.warn('JSON 파싱 실패:', e, '원본 응답:', responseText);
|
||||||
|
|
||||||
|
// 401 응답은 인증 실패로 처리
|
||||||
|
if (response.status === 401) {
|
||||||
|
return {
|
||||||
|
error: {
|
||||||
|
message: '회원가입 권한이 없습니다. Supabase 설정 또는 권한을 확인하세요.'
|
||||||
|
},
|
||||||
|
user: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (response.status >= 200 && response.status < 300) {
|
if (response.status >= 200 && response.status < 300) {
|
||||||
// 성공 응답이지만 JSON이 아닌 경우 (빈 응답 등)
|
// 성공 응답이지만 JSON이 아닌 경우 (빈 응답 등)
|
||||||
responseData = { success: true };
|
responseData = { success: true };
|
||||||
@@ -87,6 +99,7 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
|
|||||||
return { error: { message: errorMessage }, user: null };
|
return { error: { message: errorMessage }, user: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 응답 상태 코드가 성공(2xx)이면서 사용자 데이터가 있는 경우
|
||||||
if (response.ok && responseData && responseData.id) {
|
if (response.ok && responseData && responseData.id) {
|
||||||
const user = {
|
const user = {
|
||||||
id: responseData.id,
|
id: responseData.id,
|
||||||
@@ -119,17 +132,35 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
|
|||||||
|
|
||||||
return { error: null, user };
|
return { error: null, user };
|
||||||
}
|
}
|
||||||
} else if (response.ok) {
|
}
|
||||||
// 응답이 성공이지만 사용자 정보가 없는 경우
|
// 응답이 성공(2xx)이지만 사용자 정보가 없는 경우 또는 응답 본문이 비어있는 경우
|
||||||
showAuthToast('회원가입 성공', '계정이 생성되었습니다. 로그인해주세요.', 'default');
|
else if (response.ok) {
|
||||||
|
// 응답 본문이 비어 있는 경우는 서버가 성공을 반환했지만 데이터가 없는 경우 (일부 Supabase 버전에서 발생)
|
||||||
|
showAuthToast('회원가입 요청 완료', '회원가입 요청이 처리되었습니다. 이메일을 확인하거나 로그인을 시도해보세요.', 'default');
|
||||||
return {
|
return {
|
||||||
error: null,
|
error: null,
|
||||||
user: { email },
|
user: { email },
|
||||||
message: '회원가입 처리 완료'
|
message: '회원가입 처리 완료'
|
||||||
};
|
};
|
||||||
} else {
|
}
|
||||||
// 예상치 못한 응답 형식
|
// 401 오류인 경우 인증 실패로 처리
|
||||||
const errorMessage = '회원가입 처리 중 오류가 발생했습니다. 나중에 다시 시도하세요.';
|
else if (response.status === 401) {
|
||||||
|
const errorMessage = '회원가입 권한이 없습니다. Supabase 설정 또는 권한을 확인하세요.';
|
||||||
|
showAuthToast('회원가입 실패', errorMessage, 'destructive');
|
||||||
|
return { error: { message: errorMessage }, user: null };
|
||||||
|
}
|
||||||
|
// 다른 모든 오류 상태
|
||||||
|
else {
|
||||||
|
// 응답 상태 코드에 따른 오류 메시지
|
||||||
|
let errorMessage;
|
||||||
|
if (response.status === 400) {
|
||||||
|
errorMessage = '잘못된 요청 형식입니다. 입력 데이터를 확인하세요.';
|
||||||
|
} else if (response.status === 500) {
|
||||||
|
errorMessage = '서버 내부 오류가 발생했습니다. 나중에 다시 시도하세요.';
|
||||||
|
} else {
|
||||||
|
errorMessage = `회원가입 처리 중 오류가 발생했습니다 (${response.status}). 나중에 다시 시도하세요.`;
|
||||||
|
}
|
||||||
|
|
||||||
showAuthToast('회원가입 실패', errorMessage, 'destructive');
|
showAuthToast('회원가입 실패', errorMessage, 'destructive');
|
||||||
return { error: { message: errorMessage }, user: null };
|
return { error: { message: errorMessage }, user: null };
|
||||||
}
|
}
|
||||||
@@ -143,7 +174,12 @@ export const signUpWithDirectApi = async (email: string, password: string, usern
|
|||||||
// 오류 메시지 설정 및 프록시 추천
|
// 오류 메시지 설정 및 프록시 추천
|
||||||
let errorMessage = error.message || '알 수 없는 오류가 발생했습니다.';
|
let errorMessage = error.message || '알 수 없는 오류가 발생했습니다.';
|
||||||
|
|
||||||
if (errorMessage.includes('Failed to fetch') ||
|
// 타임아웃 오류 감지
|
||||||
|
if (errorMessage.includes('timed out') || errorMessage.includes('timeout')) {
|
||||||
|
errorMessage = '서버 응답 시간이 초과되었습니다. 네트워크 상태를 확인하고 다시 시도하세요.';
|
||||||
|
}
|
||||||
|
// CORS 또는 네트워크 오류 감지
|
||||||
|
else if (errorMessage.includes('Failed to fetch') ||
|
||||||
errorMessage.includes('NetworkError') ||
|
errorMessage.includes('NetworkError') ||
|
||||||
errorMessage.includes('CORS')) {
|
errorMessage.includes('CORS')) {
|
||||||
if (!usingProxy) {
|
if (!usingProxy) {
|
||||||
|
|||||||
@@ -8,7 +8,20 @@ export const getSupabaseUrl = () => {
|
|||||||
const useProxy = localStorage.getItem('use_cors_proxy') === 'true';
|
const useProxy = localStorage.getItem('use_cors_proxy') === 'true';
|
||||||
const proxyType = localStorage.getItem('proxy_type') || 'cloudflare';
|
const proxyType = localStorage.getItem('proxy_type') || 'cloudflare';
|
||||||
|
|
||||||
if (useProxy) {
|
// HTTP URL 사용 시 자동으로 프록시 활성화
|
||||||
|
const isHttpUrl = storedUrl.startsWith('http:') && !storedUrl.startsWith('http://localhost');
|
||||||
|
if (isHttpUrl && !useProxy) {
|
||||||
|
// 자동으로 프록시 설정 (Cloudflare)
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
localStorage.setItem('proxy_type', 'cloudflare');
|
||||||
|
console.log('HTTP URL 감지: CORS 프록시 자동 활성화 (Cloudflare)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 프록시 사용 여부 재확인 (자동 활성화 후)
|
||||||
|
const shouldUseProxy = localStorage.getItem('use_cors_proxy') === 'true';
|
||||||
|
const currentProxyType = localStorage.getItem('proxy_type') || 'cloudflare';
|
||||||
|
|
||||||
|
if (shouldUseProxy) {
|
||||||
// URL에 이미 프로토콜이 포함되어 있는지 확인
|
// URL에 이미 프로토콜이 포함되어 있는지 확인
|
||||||
const cleanUrl = storedUrl.trim();
|
const cleanUrl = storedUrl.trim();
|
||||||
const hasProtocol = cleanUrl.startsWith('http://') || cleanUrl.startsWith('https://');
|
const hasProtocol = cleanUrl.startsWith('http://') || cleanUrl.startsWith('https://');
|
||||||
@@ -17,7 +30,7 @@ export const getSupabaseUrl = () => {
|
|||||||
// 선택된 프록시 타입에 따라 URL 생성
|
// 선택된 프록시 타입에 따라 URL 생성
|
||||||
let proxyUrl = '';
|
let proxyUrl = '';
|
||||||
|
|
||||||
switch (proxyType) {
|
switch (currentProxyType) {
|
||||||
case 'corsproxy.io':
|
case 'corsproxy.io':
|
||||||
// 주의: 쿼리 파라미터가 포함된 URL에서 발생하는 문제를 해결하기 위해
|
// 주의: 쿼리 파라미터가 포함된 URL에서 발생하는 문제를 해결하기 위해
|
||||||
// 전체 URL을 인코딩하고 끝에 슬래시 추가
|
// 전체 URL을 인코딩하고 끝에 슬래시 추가
|
||||||
@@ -72,6 +85,21 @@ export const getSupabaseKey = () => {
|
|||||||
// CORS 프록시 사용 여부 설정
|
// CORS 프록시 사용 여부 설정
|
||||||
export const useCorsProxy = (enabled: boolean) => {
|
export const useCorsProxy = (enabled: boolean) => {
|
||||||
localStorage.setItem('use_cors_proxy', enabled.toString());
|
localStorage.setItem('use_cors_proxy', enabled.toString());
|
||||||
|
|
||||||
|
// HTTP URL 사용 시 프록시 비활성화 방지
|
||||||
|
if (!enabled) {
|
||||||
|
const storedUrl = localStorage.getItem('supabase_url');
|
||||||
|
const isHttpUrl = storedUrl && storedUrl.startsWith('http:') && !storedUrl.startsWith('http://localhost');
|
||||||
|
|
||||||
|
if (isHttpUrl) {
|
||||||
|
// HTTP URL에서는 프록시를 강제로 유지
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
console.warn('경고: HTTP URL 사용 시 CORS 프록시를 비활성화할 수 없습니다. 프록시가 자동으로 유지됩니다.');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
// CORS 프록시 유형 설정
|
// CORS 프록시 유형 설정
|
||||||
@@ -86,6 +114,16 @@ export const getProxyType = () => {
|
|||||||
|
|
||||||
// CORS 프록시 사용 여부 확인
|
// CORS 프록시 사용 여부 확인
|
||||||
export const isCorsProxyEnabled = () => {
|
export const isCorsProxyEnabled = () => {
|
||||||
|
// HTTP URL 사용 시 자동으로 프록시 활성화
|
||||||
|
const storedUrl = localStorage.getItem('supabase_url');
|
||||||
|
const isHttpUrl = storedUrl && storedUrl.startsWith('http:') && !storedUrl.startsWith('http://localhost');
|
||||||
|
|
||||||
|
if (isHttpUrl) {
|
||||||
|
// HTTP URL에서는 프록시 자동 활성화
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return localStorage.getItem('use_cors_proxy') === 'true';
|
return localStorage.getItem('use_cors_proxy') === 'true';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -99,10 +137,12 @@ export const configureSupabase = (url: string, key: string, useProxy: boolean =
|
|||||||
? cleanUrl
|
? cleanUrl
|
||||||
: `http://${cleanUrl}`;
|
: `http://${cleanUrl}`;
|
||||||
|
|
||||||
// HTTP URL을 사용하고 프록시가 활성화되지 않은 경우 경고
|
// HTTP URL을 사용하고 프록시가 활성화되지 않은 경우 자동 활성화
|
||||||
const isHttpUrl = normalizedUrl.startsWith('http:') && !normalizedUrl.startsWith('http://localhost');
|
const isHttpUrl = normalizedUrl.startsWith('http:') && !normalizedUrl.startsWith('http://localhost');
|
||||||
if (isHttpUrl && !useProxy) {
|
if (isHttpUrl && !useProxy) {
|
||||||
console.warn('경고: HTTP URL을 사용하면서 CORS 프록시가 비활성화되어 있습니다. 브라우저에서 접근 문제가 발생할 수 있습니다.');
|
console.warn('경고: HTTP URL 감지, CORS 프록시 자동 활성화');
|
||||||
|
useProxy = true;
|
||||||
|
proxyType = 'cloudflare';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 로컬 스토리지에 설정 저장
|
// 로컬 스토리지에 설정 저장
|
||||||
|
|||||||
@@ -43,15 +43,17 @@ export const verifyServerConnection = async (): Promise<{
|
|||||||
const proxyType = getProxyType();
|
const proxyType = getProxyType();
|
||||||
console.log(`연결 테스트 - CORS 프록시: ${usingProxy ? '사용 중' : '미사용'}, 타입: ${proxyType}, URL: ${supabaseUrl}`);
|
console.log(`연결 테스트 - CORS 프록시: ${usingProxy ? '사용 중' : '미사용'}, 타입: ${proxyType}, URL: ${supabaseUrl}`);
|
||||||
|
|
||||||
// 단순 헬스 체크 요청
|
// 단순 헬스 체크 요청 - 무작위 쿼리 파라미터 추가
|
||||||
|
const cacheParam = `?_nocache=${Date.now()}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${supabaseUrl}/auth/v1/`, {
|
const response = await fetch(`${supabaseUrl}/auth/v1/${cacheParam}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'apikey': localStorage.getItem('supabase_key') || ''
|
'apikey': localStorage.getItem('supabase_key') || ''
|
||||||
},
|
},
|
||||||
signal: AbortSignal.timeout(8000) // 타임아웃 시간 증가
|
signal: AbortSignal.timeout(15000) // 타임아웃 시간 증가
|
||||||
});
|
});
|
||||||
|
|
||||||
const elapsed = Date.now() - start;
|
const elapsed = Date.now() - start;
|
||||||
@@ -76,20 +78,24 @@ export const verifyServerConnection = async (): Promise<{
|
|||||||
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
||||||
const originalUrl = getOriginalSupabaseUrl();
|
const originalUrl = getOriginalSupabaseUrl();
|
||||||
if (originalUrl.startsWith('http:') && !usingProxy) {
|
if (originalUrl.startsWith('http:') && !usingProxy) {
|
||||||
|
// 자동으로 프록시 활성화
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
localStorage.setItem('proxy_type', 'cloudflare');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connected: false,
|
connected: false,
|
||||||
message: 'HTTP URL에 직접 접근할 수 없습니다. CORS 프록시를 활성화하세요.'
|
message: 'HTTP URL에 직접 접근할 수 없어 CORS 프록시를 자동으로 활성화했습니다. 페이지를 새로고침하고 다시 시도하세요.'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 대체 경로로 상태 확인
|
// 대체 경로로 상태 확인 - 무작위 쿼리 파라미터 추가
|
||||||
const altResponse = await fetch(`${supabaseUrl}/`, {
|
const altResponse = await fetch(`${supabaseUrl}/${cacheParam}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
signal: AbortSignal.timeout(8000)
|
signal: AbortSignal.timeout(15000) // 타임아웃 시간 증가
|
||||||
});
|
});
|
||||||
|
|
||||||
// 어떤 응답이라도 오면 서버가 살아있다고 간주
|
// 어떤 응답이라도 오면 서버가 살아있다고 간주
|
||||||
@@ -121,7 +127,7 @@ export const verifyServerConnection = async (): Promise<{
|
|||||||
errorMessage = '네트워크 연결 실패';
|
errorMessage = '네트워크 연결 실패';
|
||||||
} else if (error.message.includes('TypeError')) {
|
} else if (error.message.includes('TypeError')) {
|
||||||
errorMessage = '네트워크 요청 형식 오류';
|
errorMessage = '네트워크 요청 형식 오류';
|
||||||
} else if (error.message.includes('timeout')) {
|
} else if (error.message.includes('timeout') || error.message.includes('timed out')) {
|
||||||
errorMessage = '서버 응답 시간 초과';
|
errorMessage = '서버 응답 시간 초과';
|
||||||
} else if (error.message.includes('aborted')) {
|
} else if (error.message.includes('aborted')) {
|
||||||
errorMessage = '요청이 중단됨';
|
errorMessage = '요청이 중단됨';
|
||||||
@@ -133,7 +139,11 @@ export const verifyServerConnection = async (): Promise<{
|
|||||||
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
||||||
const originalUrl = getOriginalSupabaseUrl();
|
const originalUrl = getOriginalSupabaseUrl();
|
||||||
if (originalUrl.startsWith('http:') && !usingProxy) {
|
if (originalUrl.startsWith('http:') && !usingProxy) {
|
||||||
errorMessage = 'HTTP URL에 직접 접근할 수 없습니다. CORS 프록시를 활성화하세요.';
|
// 자동으로 프록시 활성화
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
localStorage.setItem('proxy_type', 'cloudflare');
|
||||||
|
|
||||||
|
errorMessage = 'HTTP URL에 직접 접근할 수 없어 CORS 프록시를 자동으로 활성화했습니다. 페이지를 새로고침하고 다시 시도하세요.';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cloudflare 프록시 추천 메시지 추가
|
// Cloudflare 프록시 추천 메시지 추가
|
||||||
@@ -196,7 +206,7 @@ export const verifySupabaseConnection = async (): Promise<{
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'apikey': localStorage.getItem('supabase_key') || ''
|
'apikey': localStorage.getItem('supabase_key') || ''
|
||||||
},
|
},
|
||||||
signal: AbortSignal.timeout(8000)
|
signal: AbortSignal.timeout(15000) // 타임아웃 시간 증가
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`경로 ${path} 응답 상태:`, response.status);
|
console.log(`경로 ${path} 응답 상태:`, response.status);
|
||||||
@@ -217,9 +227,13 @@ export const verifySupabaseConnection = async (): Promise<{
|
|||||||
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
// HTTP URL을 사용하는데 프록시가 비활성화된 경우
|
||||||
const originalUrl = getOriginalSupabaseUrl();
|
const originalUrl = getOriginalSupabaseUrl();
|
||||||
if (originalUrl.startsWith('http:') && !usingProxy) {
|
if (originalUrl.startsWith('http:') && !usingProxy) {
|
||||||
|
// 자동으로 프록시 활성화
|
||||||
|
localStorage.setItem('use_cors_proxy', 'true');
|
||||||
|
localStorage.setItem('proxy_type', 'cloudflare');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
connected: false,
|
connected: false,
|
||||||
message: 'HTTP URL에 직접 접근할 수 없습니다. CORS 프록시를 활성화하세요.',
|
message: 'HTTP URL에 직접 접근할 수 없어 CORS 프록시를 자동으로 활성화했습니다. 페이지를 새로고침하고 다시 시도하세요.',
|
||||||
details: 'CORS 제한으로 인해 HTTP URL에 직접 접근할 수 없습니다'
|
details: 'CORS 제한으로 인해 HTTP URL에 직접 접근할 수 없습니다'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user