120 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/**
 | 
						|
 * API 호출을 위한 편의 함수
 | 
						|
 *
 | 
						|
 * @template T - 응답 데이터의 타입
 | 
						|
 * @param path - API 엔드포인트 경로 (예: '/users', '/users/1')
 | 
						|
 * @param options - 요청 및 에러 처리 옵션
 | 
						|
 * @returns Promise<T> - API 응답 데이터
 | 
						|
 *
 | 
						|
 * @example
 | 
						|
 * // GET 요청 (기본 - 전역 로딩 자동 적용)
 | 
						|
 * const users = await useApi<User[]>('/users')
 | 
						|
 *
 | 
						|
 * // POST 요청 (커스텀 로딩 메시지)
 | 
						|
 * const newUser = await useApi<User>('/users', {
 | 
						|
 *   method: 'POST',
 | 
						|
 *   body: { name: 'John', email: 'john@example.com' },
 | 
						|
 *   loadingMessage: '사용자를 생성하는 중...'
 | 
						|
 * })
 | 
						|
 *
 | 
						|
 * // 전역 로딩 없이 API 호출
 | 
						|
 * const data = await useApi<User[]>('/users', {
 | 
						|
 *   useGlobalLoading: false
 | 
						|
 * })
 | 
						|
 *
 | 
						|
 * // 에러를 직접 처리
 | 
						|
 * try {
 | 
						|
 *   const data = await useApi<User[]>('/users', { handleError: false })
 | 
						|
 * } catch (error) {
 | 
						|
 *   // 직접 에러 처리
 | 
						|
 * }
 | 
						|
 *
 | 
						|
 * // FormData 업로드
 | 
						|
 * const formData = new FormData()
 | 
						|
 * formData.append('file', file)
 | 
						|
 * await useApi('/upload', {
 | 
						|
 *   method: 'POST',
 | 
						|
 *   body: formData,
 | 
						|
 *   loadingMessage: '파일을 업로드하는 중...'
 | 
						|
 * })
 | 
						|
 */
 | 
						|
export const useApi = async <T>(
 | 
						|
  path: string,
 | 
						|
  options?: {
 | 
						|
    // API 요청 옵션
 | 
						|
    method?: string;
 | 
						|
    body?: any;
 | 
						|
    headers?: Record<string, string>;
 | 
						|
    // 에러 처리 옵션
 | 
						|
    handleError?: boolean; // true: 에러를 null로 반환, false: 에러를 다시 던짐
 | 
						|
    showAlert?: boolean; // true: 에러 시 alert 표시
 | 
						|
    // 로딩 옵션
 | 
						|
    loadingMessage?: string; // 로딩 메시지
 | 
						|
    useGlobalLoading?: boolean; // 전역 로딩 사용 여부 (기본값: true)
 | 
						|
  }
 | 
						|
): Promise<T> => {
 | 
						|
  const { withLoading } = useLoading();
 | 
						|
 | 
						|
  // API 호출 로직을 별도 함수로 분리
 | 
						|
  const apiCall = async (): Promise<T> => {
 | 
						|
    const { $api } = useNuxtApp();
 | 
						|
 | 
						|
    // 기본값 설정
 | 
						|
    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; // 에러를 다시 던짐
 | 
						|
      }
 | 
						|
    });
 | 
						|
  };
 | 
						|
 | 
						|
  // 전역 로딩 사용 여부 확인 (기본값: true)
 | 
						|
  const shouldUseLoading = options?.useGlobalLoading !== false;
 | 
						|
 | 
						|
  if (shouldUseLoading) {
 | 
						|
    // 전역 로딩과 함께 API 호출
 | 
						|
    return await withLoading(
 | 
						|
      apiCall,
 | 
						|
      options?.loadingMessage || "데이터를 불러오는 중..."
 | 
						|
    );
 | 
						|
  } else {
 | 
						|
    // 전역 로딩 없이 API 호출
 | 
						|
    return await apiCall();
 | 
						|
  }
 | 
						|
};
 |