diff --git a/composables/useApi.ts b/composables/useApi.ts index ce66a77..aa1b1eb 100644 --- a/composables/useApi.ts +++ b/composables/useApi.ts @@ -3,11 +3,11 @@ * * @template T - 응답 데이터의 타입 * @param path - API 엔드포인트 경로 (예: '/users', '/users/1') - * @param opts - 요청 옵션 (method, body, headers 등) + * @param options - 요청 및 에러 처리 옵션 * @returns Promise - API 응답 데이터 * * @example - * // GET 요청 + * // GET 요청 (기본) * const users = await useApi('/users') * * // POST 요청 @@ -16,21 +16,75 @@ * body: { name: 'John', email: 'john@example.com' } * }) * - * // PUT 요청 - * const updatedUser = await useApi('/users/1', { - * method: 'PUT', - * body: { name: 'John Updated' } - * }) + * // 에러 시 alert 표시 + * const data = await useApi('/users', { showAlert: true }) * - * // DELETE 요청 - * await useApi('/users/1', { method: 'DELETE' }) + * // 에러를 직접 처리 + * try { + * const data = await useApi('/users', { handleError: false }) + * } catch (error) { + * // 직접 에러 처리 + * } * * // FormData 업로드 * const formData = new FormData() * formData.append('file', file) * await useApi('/upload', { method: 'POST', body: formData }) */ -export const useApi = (path: string, opts?: any): Promise => { +export const useApi = async ( + path: string, + options?: { + // API 요청 옵션 + method?: string; + body?: any; + headers?: Record; + // 에러 처리 옵션 + handleError?: boolean; // true: 에러를 null로 반환, false: 에러를 다시 던짐 + showAlert?: boolean; // true: 에러 시 alert 표시 + } +): Promise => { const { $api } = useNuxtApp(); - return ($api as any)(path, opts); + + // 기본값 설정 + const { + method = "GET", + body, + headers, + handleError = true, + showAlert = true, + } = options || {}; + + // API 요청 옵션 구성 + const apiOpts = { + method, + ...(body && { body }), + ...(headers && { headers }), + }; + + return ($api as any)(path, apiOpts).catch((error: any) => { + // 사용자에게 알림 표시 + if (showAlert) { + const status = error.response?.status; + let message = + status === 404 + ? "요청한 리소스를 찾을 수 없습니다." + : status === 500 + ? "서버 오류가 발생했습니다." + : "요청 처리 중 오류가 발생했습니다."; + + // 서버에서 온 에러 메시지가 있으면 우선 사용 + if (error.response?._data?.description) { + message = error.response._data.description; + } + + alert(message); + } + + // 에러 처리 방식에 따라 반환 + if (handleError) { + return null as T; // 에러를 null로 반환 + } else { + throw error; // 에러를 다시 던짐 + } + }); }; diff --git a/pages/[tabId]/index.vue b/pages/[tabId]/index.vue index 1672772..3b7404e 100644 --- a/pages/[tabId]/index.vue +++ b/pages/[tabId]/index.vue @@ -29,13 +29,16 @@

+

@@ -119,6 +122,47 @@ definePageMeta({ }); const userStore = useUserStore(); + +// 테스트 다운로드 함수 (자동 에러 처리) +const apiTest = async () => { + const response = await useApi>( + "/admin/common-codes/USER_STATUS_ACTIVE222" + ); + + if (response) { + console.log("response:", response); + } +}; + +// 직접 에러 처리하는 함수 예시 +const apiTestWithCustomError = async () => { + try { + const response = await useApi>( + "/admin/common-codes/USER_STATUS_ACTIVE222", + { + handleError: false, // 에러를 직접 처리하겠다는 의미 + showAlert: false, // alert는 표시하지 않음 + } + ); + + if (response) { + console.log("response:", response); + } + } catch (error: any) { + // 에러 타입에 따른 세밀한 처리 + if (error.response?.status === 404) { + alert("[errorCustomHandler]요청한 코드를 찾을 수 없습니다."); + } else if (error.response?.status === 403) { + alert("[errorCustomHandler]접근 권한이 없습니다."); + } else if (error.response?.status >= 500) { + alert( + "[errorCustomHandler]서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요." + ); + } else { + alert("[errorCustomHandler]알 수 없는 오류가 발생했습니다."); + } + } +};