From 5b73eddd4f40612b465ceccdcf0eb686b1878845 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 13:48:29 +0000 Subject: [PATCH] Refactor auth.utils.ts Refactor auth.utils.ts into smaller modules for better organization and maintainability. Split functions into networkUtils.ts, responseUtils.ts, and toastUtils.ts based on their purpose. --- src/contexts/auth/resetPassword.ts | 3 +- src/contexts/auth/signIn.ts | 8 +- src/contexts/auth/signOut.ts | 3 +- src/contexts/auth/signUp.ts | 7 +- src/utils/auth/index.ts | 6 + .../auth/networkUtils.ts} | 117 ++---------------- src/utils/auth/responseUtils.ts | 86 +++++++++++++ src/utils/auth/toastUtils.ts | 13 ++ src/utils/auth/validationUtils.ts | 13 ++ 9 files changed, 143 insertions(+), 113 deletions(-) create mode 100644 src/utils/auth/index.ts rename src/{contexts/auth/auth.utils.ts => utils/auth/networkUtils.ts} (53%) create mode 100644 src/utils/auth/responseUtils.ts create mode 100644 src/utils/auth/toastUtils.ts create mode 100644 src/utils/auth/validationUtils.ts diff --git a/src/contexts/auth/resetPassword.ts b/src/contexts/auth/resetPassword.ts index 34d8ba6..1b5a916 100644 --- a/src/contexts/auth/resetPassword.ts +++ b/src/contexts/auth/resetPassword.ts @@ -1,6 +1,5 @@ - import { supabase } from '@/lib/supabase'; -import { handleNetworkError, showAuthToast } from './auth.utils'; +import { handleNetworkError, showAuthToast } from '@/utils/auth'; export const resetPassword = async (email: string) => { try { diff --git a/src/contexts/auth/signIn.ts b/src/contexts/auth/signIn.ts index 362f132..db25272 100644 --- a/src/contexts/auth/signIn.ts +++ b/src/contexts/auth/signIn.ts @@ -1,6 +1,10 @@ - import { supabase } from '@/lib/supabase'; -import { handleNetworkError, parseResponse, showAuthToast, verifyServerConnection } from './auth.utils'; +import { + handleNetworkError, + parseResponse, + showAuthToast, + verifyServerConnection +} from '@/utils/auth'; export const signIn = async (email: string, password: string) => { try { diff --git a/src/contexts/auth/signOut.ts b/src/contexts/auth/signOut.ts index cf22ad1..9321fa8 100644 --- a/src/contexts/auth/signOut.ts +++ b/src/contexts/auth/signOut.ts @@ -1,6 +1,5 @@ - import { supabase } from '@/lib/supabase'; -import { showAuthToast } from './auth.utils'; +import { showAuthToast } from '@/utils/auth'; export const signOut = async (): Promise => { try { diff --git a/src/contexts/auth/signUp.ts b/src/contexts/auth/signUp.ts index 195772a..802befc 100644 --- a/src/contexts/auth/signUp.ts +++ b/src/contexts/auth/signUp.ts @@ -1,6 +1,9 @@ - import { supabase } from '@/lib/supabase'; -import { handleNetworkError, parseResponse, showAuthToast } from './auth.utils'; +import { + handleNetworkError, + parseResponse, + showAuthToast +} from '@/utils/auth'; export const signUp = async (email: string, password: string, username: string) => { try { diff --git a/src/utils/auth/index.ts b/src/utils/auth/index.ts new file mode 100644 index 0000000..4615586 --- /dev/null +++ b/src/utils/auth/index.ts @@ -0,0 +1,6 @@ + +// 모든 인증 관련 유틸리티 함수들을 내보냅니다 +export * from './toastUtils'; +export * from './networkUtils'; +export * from './responseUtils'; +export * from './validationUtils'; diff --git a/src/contexts/auth/auth.utils.ts b/src/utils/auth/networkUtils.ts similarity index 53% rename from src/contexts/auth/auth.utils.ts rename to src/utils/auth/networkUtils.ts index a1eeccb..39fb87f 100644 --- a/src/contexts/auth/auth.utils.ts +++ b/src/utils/auth/networkUtils.ts @@ -1,13 +1,9 @@ -import { toast } from '@/hooks/useToast.wrapper'; import { supabase } from '@/lib/supabase'; -// 토스트 메시지 표시 유틸리티 함수 -export const showAuthToast = (title: string, description: string, variant: 'default' | 'destructive' = 'default') => { - toast({ title, description, variant }); -}; - -// 에러 메시지 처리 유틸리티 함수 +/** + * 네트워크 오류 메시지 처리 유틸리티 함수 + */ export const handleNetworkError = (error: any): string => { if (error.message && error.message.includes('fetch')) { return '서버 연결에 실패했습니다. 네트워크 연결을 확인해주세요.'; @@ -26,91 +22,9 @@ export const handleNetworkError = (error: any): string => { return error.message || '예상치 못한 오류가 발생했습니다.'; }; -// 응답 파싱 유틸리티 함수 개선 -export const parseResponse = async (response: Response) => { - try { - // 비어있는 응답 또는 401 응답을 먼저 확인 - if (response.status === 401) { - if (response.headers.get('content-length') === '0' || await response.clone().text() === '') { - return { - error: '인증 실패: 잘못된 인증 정보 또는 서버 설정 문제', - status: 401 - }; - } - } - - // 응답 내용 확인 (디버깅용) - const responseText = await response.text(); - console.log('응답 원본:', responseText, 'Status:', response.status); - - // 빈 응답 또는 공백만 있는 응답 처리 - if (!responseText || responseText.trim() === '') { - if (response.status === 401) { - return { - error: '인증 실패: 서버가 인증을 거부했습니다.', - status: 401 - }; - } else if (response.status === 404) { - return { - error: '서버 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.', - status: 404 - }; - } else if (response.status >= 200 && response.status < 300) { - return { - success: true, - status: response.status, - message: '서버가 성공 상태를 반환했지만 응답 내용이 없습니다.' - }; - } else { - return { - error: `서버가 빈 응답을 반환했습니다 (상태 코드: ${response.status})`, - status: response.status - }; - } - } - - try { - return JSON.parse(responseText); - } catch (parseError) { - console.error('JSON 파싱 오류:', parseError, '원본 텍스트:', responseText); - - // HTTP 상태 코드에 따른 적절한 오류 메시지 반환 - if (response.status === 401) { - return { - error: '인증 실패: 이메일 또는 비밀번호가 올바르지 않습니다.', - status: 401 - }; - } else if (response.status === 404) { - return { - error: '서버 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.', - status: 404 - }; - } else if (response.status >= 500) { - return { - error: '서버 내부 오류가 발생했습니다.', - status: response.status - }; - } else if (response.status >= 200 && response.status < 300) { - return { - success: true, - status: response.status, - message: '서버가 성공 상태를 반환했지만 JSON 형식이 아닙니다.' - }; - } else { - return { - error: `응답 형식 오류 (상태 코드: ${response.status}): 서버가 올바른 JSON 응답을 반환하지 않았습니다.`, - status: response.status, - rawResponse: responseText - }; - } - } - } catch (parseError) { - console.error('응답 파싱 오류:', parseError); - throw parseError; - } -}; - -// CORS 문제 확인 +/** + * CORS 문제 확인 + */ export const hasCorsIssue = (error: any): boolean => { if (!error) return false; @@ -123,7 +37,9 @@ export const hasCorsIssue = (error: any): boolean => { ); }; -// Supabase 연결 상태 확인 +/** + * Supabase 연결 상태 확인 + */ export const checkSupabaseConnection = async (): Promise => { try { const { data, error } = await supabase.auth.getSession(); @@ -150,7 +66,9 @@ export const checkSupabaseConnection = async (): Promise => { } }; -// 서버 연결 상태 검사 (개선 버전) +/** + * 서버 연결 상태 검사 + */ export const verifyServerConnection = async (): Promise<{ connected: boolean; message: string; @@ -216,14 +134,3 @@ export const verifyServerConnection = async (): Promise<{ }; } }; - -// 서버 URL 검증 -export const validateServerUrl = (url: string): boolean => { - try { - // URL 유효성 검사 - new URL(url); - return true; - } catch (e) { - return false; - } -}; diff --git a/src/utils/auth/responseUtils.ts b/src/utils/auth/responseUtils.ts new file mode 100644 index 0000000..cd5c34a --- /dev/null +++ b/src/utils/auth/responseUtils.ts @@ -0,0 +1,86 @@ + +/** + * 응답 파싱 유틸리티 함수 + */ +export const parseResponse = async (response: Response) => { + try { + // 비어있는 응답 또는 401 응답을 먼저 확인 + if (response.status === 401) { + if (response.headers.get('content-length') === '0' || await response.clone().text() === '') { + return { + error: '인증 실패: 잘못된 인증 정보 또는 서버 설정 문제', + status: 401 + }; + } + } + + // 응답 내용 확인 (디버깅용) + const responseText = await response.text(); + console.log('응답 원본:', responseText, 'Status:', response.status); + + // 빈 응답 또는 공백만 있는 응답 처리 + if (!responseText || responseText.trim() === '') { + if (response.status === 401) { + return { + error: '인증 실패: 서버가 인증을 거부했습니다.', + status: 401 + }; + } else if (response.status === 404) { + return { + error: '서버 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.', + status: 404 + }; + } else if (response.status >= 200 && response.status < 300) { + return { + success: true, + status: response.status, + message: '서버가 성공 상태를 반환했지만 응답 내용이 없습니다.' + }; + } else { + return { + error: `서버가 빈 응답을 반환했습니다 (상태 코드: ${response.status})`, + status: response.status + }; + } + } + + try { + return JSON.parse(responseText); + } catch (parseError) { + console.error('JSON 파싱 오류:', parseError, '원본 텍스트:', responseText); + + // HTTP 상태 코드에 따른 적절한 오류 메시지 반환 + if (response.status === 401) { + return { + error: '인증 실패: 이메일 또는 비밀번호가 올바르지 않습니다.', + status: 401 + }; + } else if (response.status === 404) { + return { + error: '서버 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.', + status: 404 + }; + } else if (response.status >= 500) { + return { + error: '서버 내부 오류가 발생했습니다.', + status: response.status + }; + } else if (response.status >= 200 && response.status < 300) { + return { + success: true, + status: response.status, + message: '서버가 성공 상태를 반환했지만 JSON 형식이 아닙니다.' + }; + } else { + return { + error: `응답 형식 오류 (상태 코드: ${response.status}): 서버가 올바른 JSON 응답을 반환하지 않았습니다.`, + status: response.status, + rawResponse: responseText + }; + } + } + } catch (parseError) { + console.error('응답 파싱 오류:', parseError); + throw parseError; + } +}; diff --git a/src/utils/auth/toastUtils.ts b/src/utils/auth/toastUtils.ts new file mode 100644 index 0000000..1a808dd --- /dev/null +++ b/src/utils/auth/toastUtils.ts @@ -0,0 +1,13 @@ + +import { toast } from '@/hooks/useToast.wrapper'; + +/** + * 인증 관련 토스트 메시지 표시 유틸리티 함수 + */ +export const showAuthToast = ( + title: string, + description: string, + variant: 'default' | 'destructive' = 'default' +) => { + toast({ title, description, variant }); +}; diff --git a/src/utils/auth/validationUtils.ts b/src/utils/auth/validationUtils.ts new file mode 100644 index 0000000..91924c2 --- /dev/null +++ b/src/utils/auth/validationUtils.ts @@ -0,0 +1,13 @@ + +/** + * 서버 URL 검증 + */ +export const validateServerUrl = (url: string): boolean => { + try { + // URL 유효성 검사 + new URL(url); + return true; + } catch (e) { + return false; + } +};