Refactor: Improve code organization

Refactor signInUtils.ts and networkUtils.ts into smaller, more manageable files.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-18 06:18:00 +00:00
parent 609c6703cc
commit 6861f4d88b
10 changed files with 245 additions and 214 deletions

View File

@@ -5,6 +5,8 @@ export * from './networkUtils';
export * from './responseUtils';
export * from './validationUtils';
export * from './handleNetworkError';
export * from './loginUtils';
// 새로운 네트워크 모듈 직접 내보냅니다 (선택적)
// 모듈 직접 접근을 위한 내보내기
export * from './network';
export * from './login';

View File

@@ -0,0 +1,40 @@
/**
* 로그인 오류 메시지를 처리하는 유틸리티 함수
*/
export const getLoginErrorMessage = (error: any): string => {
let errorMessage = "로그인에 실패했습니다.";
// Supabase 오류 메시지 처리
if (error.message) {
if (error.message.includes("Invalid login credentials")) {
errorMessage = "이메일 또는 비밀번호가 올바르지 않습니다.";
} else if (error.message.includes("Email not confirmed")) {
errorMessage = "이메일 인증이 완료되지 않았습니다. 이메일을 확인해주세요.";
} else if (error.message.includes("JSON")) {
errorMessage = "서버 응답 오류: JSON 파싱 실패. 네트워크 연결을 확인하세요.";
} else if (error.message.includes("fetch") || error.message.includes("네트워크")) {
errorMessage = "네트워크 오류: 서버 연결에 실패했습니다.";
} else if (error.message.includes("404") || error.message.includes("Not Found")) {
errorMessage = "서버 오류: API 경로를 찾을 수 없습니다. 서버 설정을 확인하세요.";
} else {
errorMessage = `오류: ${error.message}`;
}
}
return errorMessage;
};
/**
* CORS 또는 JSON 관련 오류인지 확인합니다.
*/
export const isCorsOrJsonError = (errorMessage: string | null): boolean => {
if (!errorMessage) return false;
return (
errorMessage.includes('JSON') ||
errorMessage.includes('서버 응답') ||
errorMessage.includes('404') ||
errorMessage.includes('Not Found')
);
};

View File

@@ -0,0 +1,4 @@
// 로그인 관련 모든 유틸리티 내보내기
export * from './errorHandlers';
export * from './toastHandlers';

View File

@@ -0,0 +1,24 @@
import { toast } from "@/components/ui/use-toast";
/**
* 로그인 성공 시 사용자에게 알림을 표시합니다.
*/
export const showLoginSuccessToast = (mode?: string) => {
toast({
title: "로그인 성공",
description: mode ? `${mode}로 로그인되었습니다.` : "환영합니다! 대시보드로 이동합니다.",
variant: "default"
});
};
/**
* 로그인 오류 시 사용자에게 알림을 표시합니다.
*/
export const showLoginErrorToast = (errorMessage: string) => {
toast({
title: "로그인 실패",
description: errorMessage,
variant: "destructive"
});
};

View File

@@ -1,68 +1,9 @@
import { toast } from "@/components/ui/use-toast";
/**
* 로그인 오류 메시지를 처리하는 유틸리티 함수
*/
export const getLoginErrorMessage = (error: any): string => {
let errorMessage = "로그인에 실패했습니다.";
// Supabase 오류 메시지 처리
if (error.message) {
if (error.message.includes("Invalid login credentials")) {
errorMessage = "이메일 또는 비밀번호가 올바르지 않습니다.";
} else if (error.message.includes("Email not confirmed")) {
errorMessage = "이메일 인증이 완료되지 않았습니다. 이메일을 확인해주세요.";
} else if (error.message.includes("JSON")) {
errorMessage = "서버 응답 오류: JSON 파싱 실패. 네트워크 연결이나 CORS 설정을 확인하세요.";
} else if (error.message.includes("CORS") || error.message.includes("프록시")) {
errorMessage = "CORS 오류: 프록시 설정을 확인하거나 다른 프록시를 시도해보세요.";
} else if (error.message.includes("fetch") || error.message.includes("네트워크")) {
errorMessage = "네트워크 오류: 서버 연결에 실패했습니다.";
} else if (error.message.includes("404") || error.message.includes("Not Found")) {
errorMessage = "서버 오류: API 경로를 찾을 수 없습니다. 서버 설정을 확인하세요.";
} else {
errorMessage = `오류: ${error.message}`;
}
}
return errorMessage;
};
/**
* 로그인 성공 시 사용자에게 알림을 표시합니다.
*/
export const showLoginSuccessToast = (mode?: string) => {
toast({
title: "로그인 성공",
description: mode ? `${mode}로 로그인되었습니다.` : "환영합니다! 대시보드로 이동합니다.",
variant: "default"
});
};
/**
* 로그인 오류 시 사용자에게 알림을 표시합니다.
*/
export const showLoginErrorToast = (errorMessage: string) => {
toast({
title: "로그인 실패",
description: errorMessage,
variant: "destructive"
});
};
/**
* CORS 또는 JSON 관련 오류인지 확인합니다.
*/
export const isCorsOrJsonError = (errorMessage: string | null): boolean => {
if (!errorMessage) return false;
return (
errorMessage.includes('JSON') ||
errorMessage.includes('CORS') ||
errorMessage.includes('프록시') ||
errorMessage.includes('서버 응답') ||
errorMessage.includes('404') ||
errorMessage.includes('Not Found')
);
};
// 이 파일은 하위 모듈로 분리된 로그인 유틸리티를 다시 내보냅니다.
// 향후 개발에서는 직접 하위 모듈을 임포트하는 것이 권장됩니다.
export {
getLoginErrorMessage,
isCorsOrJsonError,
showLoginSuccessToast,
showLoginErrorToast
} from './login';

View File

@@ -0,0 +1,7 @@
/**
* 호환성을 위한 더미 함수들 - Cloud 환경에서는 항상 false를 반환
*/
export const hasCorsIssue = (): boolean => false;
export const handleHttpUrlWithoutProxy = (): boolean => true;
export const logProxyInfo = (): void => {};

View File

@@ -0,0 +1,75 @@
import { getSupabaseUrl } from '@/lib/supabase/config';
/**
* 기본 서버 연결 상태 검사 유틸리티
*/
export const verifyServerConnection = async (): Promise<{
connected: boolean;
message: string;
statusCode?: number;
}> => {
try {
const start = Date.now();
// Supabase URL 가져오기
const supabaseUrl = getSupabaseUrl();
if (!supabaseUrl) {
return {
connected: false,
message: 'Supabase URL이 설정되지 않았습니다.'
};
}
// 캐시 방지용 쿼리 파라미터 추가
const cacheParam = `?_nocache=${Date.now()}`;
// 서버 연결 상태 확인
const response = await fetch(`${supabaseUrl}/auth/v1/${cacheParam}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: AbortSignal.timeout(8000)
});
const elapsed = Date.now() - start;
// 200, 401, 404 응답도 서버가 살아있다는 신호로 간주
if (response.ok || response.status === 401 || response.status === 404) {
return {
connected: true,
message: `서버 연결 성공 (응답 시간: ${elapsed}ms)`,
statusCode: response.status
};
} else {
return {
connected: false,
message: `서버 응답 오류: ${response.status} ${response.statusText}`,
statusCode: response.status
};
}
} catch (error: any) {
console.error('서버 연결 확인 중 오류:', error);
let errorMessage = '알 수 없는 네트워크 오류';
if (error.message) {
if (error.message.includes('Failed to fetch')) {
errorMessage = '서버 연결 실패';
} else if (error.message.includes('NetworkError')) {
errorMessage = '네트워크 연결 실패';
} else if (error.message.includes('timeout') || error.message.includes('timed out')) {
errorMessage = '서버 응답 시간 초과';
} else {
errorMessage = error.message;
}
}
return {
connected: false,
message: errorMessage
};
}
};

View File

@@ -0,0 +1,64 @@
import { getSupabaseUrl } from '@/lib/supabase/config';
/**
* 강화된 서버 연결 검사 - Supabase Cloud 환경에 최적화
*/
export const verifySupabaseConnection = async (): Promise<{
connected: boolean;
message: string;
statusCode?: number;
details?: string;
}> => {
const supabaseUrl = getSupabaseUrl();
if (!supabaseUrl) {
return {
connected: false,
message: 'Supabase URL이 설정되지 않았습니다'
};
}
// 무작위 쿼리 파라미터를 추가하여 캐시 방지
const cacheParam = `?_nocache=${Date.now()}`;
// 다양한 경로를 순차적으로 시도
const paths = [
'/auth/v1/',
'/',
'/rest/v1/',
'/storage/v1/'
];
for (const path of paths) {
try {
console.log(`경로 시도: ${path}`);
const response = await fetch(`${supabaseUrl}${path}${cacheParam}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: AbortSignal.timeout(8000)
});
console.log(`경로 ${path} 응답 상태:`, response.status);
// 어떤 응답이든 서버가 살아있다는 신호로 간주
return {
connected: true,
message: `서버 연결 성공 (${path})`,
statusCode: response.status,
details: `${response.status} ${response.statusText}`
};
} catch (error) {
console.warn(`${path} 경로 연결 실패:`, error);
// 계속 다음 경로 시도
}
}
// 모든 경로 시도 실패
return {
connected: false,
message: '모든 Supabase 경로에 대한 연결 시도 실패',
details: '네트워크 연결 또는 서버 주소를 확인하세요'
};
};

View File

@@ -1,9 +1,14 @@
// 네트워크 유틸리티 모듈
// 모든 네트워크 유틸리티 모듈 내보내기
export {
verifyServerConnection,
verifySupabaseConnection,
hasCorsIssue,
handleHttpUrlWithoutProxy,
logProxyInfo,
verifyServerConnection,
verifySupabaseConnection
logProxyInfo
} from './networkUtils';
// 직접 접근을 위한 개별 모듈도 내보내기
export * from './connectionVerifier';
export * from './enhancedVerifier';
export * from './compatUtils';

View File

@@ -1,145 +1,14 @@
import { getSupabaseUrl } from '@/lib/supabase/config';
// 네트워크 유틸리티 모듈을 개별 파일로 분리하여 관리하기 쉽게 구성
import { verifyServerConnection } from './connectionVerifier';
import { verifySupabaseConnection } from './enhancedVerifier';
import { hasCorsIssue, handleHttpUrlWithoutProxy, logProxyInfo } from './compatUtils';
/**
* 서버 연결 상태 검사 - Supabase Cloud 환경에 최적화
*/
export const verifyServerConnection = async (): Promise<{
connected: boolean;
message: string;
statusCode?: number;
}> => {
try {
const start = Date.now();
// Supabase URL 가져오기
const supabaseUrl = getSupabaseUrl();
if (!supabaseUrl) {
return {
connected: false,
message: 'Supabase URL이 설정되지 않았습니다.'
};
}
// 캐시 방지용 쿼리 파라미터 추가
const cacheParam = `?_nocache=${Date.now()}`;
// 서버 연결 상태 확인
const response = await fetch(`${supabaseUrl}/auth/v1/${cacheParam}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: AbortSignal.timeout(8000)
});
const elapsed = Date.now() - start;
// 200, 401, 404 응답도 서버가 살아있다는 신호로 간주
if (response.ok || response.status === 401 || response.status === 404) {
return {
connected: true,
message: `서버 연결 성공 (응답 시간: ${elapsed}ms)`,
statusCode: response.status
};
} else {
return {
connected: false,
message: `서버 응답 오류: ${response.status} ${response.statusText}`,
statusCode: response.status
};
}
} catch (error: any) {
console.error('서버 연결 확인 중 오류:', error);
let errorMessage = '알 수 없는 네트워크 오류';
if (error.message) {
if (error.message.includes('Failed to fetch')) {
errorMessage = '서버 연결 실패';
} else if (error.message.includes('NetworkError')) {
errorMessage = '네트워크 연결 실패';
} else if (error.message.includes('timeout') || error.message.includes('timed out')) {
errorMessage = '서버 응답 시간 초과';
} else {
errorMessage = error.message;
}
}
return {
connected: false,
message: errorMessage
};
}
// 모든 기능 재내보내기
export {
verifyServerConnection,
verifySupabaseConnection,
hasCorsIssue,
handleHttpUrlWithoutProxy,
logProxyInfo
};
/**
* 강화된 서버 연결 검사 - Supabase Cloud 환경에 최적화
*/
export const verifySupabaseConnection = async (): Promise<{
connected: boolean;
message: string;
statusCode?: number;
details?: string;
}> => {
const supabaseUrl = getSupabaseUrl();
if (!supabaseUrl) {
return {
connected: false,
message: 'Supabase URL이 설정되지 않았습니다'
};
}
// 무작위 쿼리 파라미터를 추가하여 캐시 방지
const cacheParam = `?_nocache=${Date.now()}`;
// 다양한 경로를 순차적으로 시도
const paths = [
'/auth/v1/',
'/',
'/rest/v1/',
'/storage/v1/'
];
for (const path of paths) {
try {
console.log(`경로 시도: ${path}`);
const response = await fetch(`${supabaseUrl}${path}${cacheParam}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
signal: AbortSignal.timeout(8000)
});
console.log(`경로 ${path} 응답 상태:`, response.status);
// 어떤 응답이든 서버가 살아있다는 신호로 간주
return {
connected: true,
message: `서버 연결 성공 (${path})`,
statusCode: response.status,
details: `${response.status} ${response.statusText}`
};
} catch (error) {
console.warn(`${path} 경로 연결 실패:`, error);
// 계속 다음 경로 시도
}
}
// 모든 경로 시도 실패
return {
connected: false,
message: '모든 Supabase 경로에 대한 연결 시도 실패',
details: '네트워크 연결 또는 서버 주소를 확인하세요'
};
};
/**
* 호환성을 위한 더미 함수들 - Cloud 환경에서는 항상 false를 반환
*/
export const hasCorsIssue = (): boolean => false;
export const handleHttpUrlWithoutProxy = (): boolean => true;
export const logProxyInfo = (): void => {};