Tanstack Query와 API 통합으로 최적화된 제품 데이터 관리 구현하기
2025-02-23 08:13:23Tanstack Query란 무엇인가?
디지털 경제의 빠른 발전 속도에서 기업의 성공을 위한 중추는 효율적인 API 통합에 있습니다. Tanstack Query는 비동기 서버 상태 처리, 캐싱 및 백그라운드 데이터 동기화에서 강력한 성능을 발휘합니다. 이는 데이터 일관성을 크게 개선하고 지연 시간을 줄이며, 대규모 조직의 제품 데이터 관리를 간편하게 만들어 줍니다.
Tanstack Query가 엔터프라이즈 제품 관리에 중요한 이유
운영의 민첩성
실시간 업데이트와 감소된 API 오버헤드는 비즈니스가 시장 변화에 신속하게 대응할 수 있도록 돕습니다. 이는 비즈니스 환경의 변동성에 대한 민첩한 적응력을 의미합니다.
개선된 사용자 경험
제품 데이터의 일관된 처리는 최종 사용자와 내부 팀이 가장 최신의 정보를 사용하도록 보장합니다. 이는 사용자 만족도를 극대화하는데 중요한 역할을 합니다.
낮은 유지 관리 비용
데이터 페칭과 오류 처리를 중앙화 함으로써 개발 팀은 중복성을 줄이고 데이터 낡음으로 인한 위험을 완화할 수 있습니다. 이를 통해 비용 절감과 기술 역량 증대를 동시에 이룰 수 있습니다.
Tanstack Query 및 개발 도구 설정
API 쿼리와 변이 작업을 시작하기 전에 Tanstack Query와 그에 수반되는 개발자 도구를 설정해야 합니다. 다음의 명령어를 프로젝트 디렉토리에서 실행하세요:
npm install @tanstack/react-query
npm install @tanstack/react-query-devtools
이후, 앱의 루트에서 QueryClient를 초기화합니다:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourAppComponents />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
export default App;
이와 같은 설정은 생산 수준의 애플리케이션에서 효율적인 상태 관리 및 디버깅에 필수적입니다.
순차 정렬된 제품 API 통합 코드 분석
1. API 요청 헬퍼
이 유틸리티 함수는 API 호출을 표준화하여 일관된 오류 처리와 응답 파싱을 제공합니다.
// api-request.ts
import { toast } from "sonner";
/**
* Helper function for API requests.
* Handles generic error messaging and returns JSON response.
*/
export const apiRequest = async (url: string, options: RequestInit) => {
const response = await fetch(url, options);
if (!response.ok) {
const errorData = await response.json();
toast.error(
"Error: " + (errorData?.res?.message?.message || "Something went wrong")
);
}
return response.json();
};
2. 제품 API 함수
이 함수들은 제품 데이터에 대한 CRUD 작업을 수행하며, 기업별 토큰과 ID를 검색하는 헬퍼 메소드를 사용합니다.
// product-api.ts
import { Product } from "@/types/product";
import { Api } from "@/utils/api/api";
import { apiRequest } from "@/utils/api/api-request";
import { getCompanyId } from "@/utils/get-company-id";
import { getCompanyToken } from "@/utils/token-utils";
const BASE_URL = `${Api}/products`;
/**
* Fetch all active products for a company.
*/
export const getAllProductsApi = async () => {
return apiRequest(`${BASE_URL}/company/${getCompanyId()}?is_active=true`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCompanyToken()}`,
},
});
};
/**
* Fetch a single product by ID.
*/
export const getSingleProductApi = async (id: string) => {
return apiRequest(`${BASE_URL}/${id}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCompanyToken()}`,
},
});
};
/**
* Create a new product.
*/
export const createProductApi = async (data: Product) => {
return apiRequest(BASE_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCompanyToken()}`,
},
body: JSON.stringify(data),
});
};
/**
* Update an existing product by ID.
*/
export const updateProductApi = async (id: string, data: Product) => {
return apiRequest(`${BASE_URL}/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCompanyToken()}`,
},
body: JSON.stringify(data),
});
};
/**
* Delete a product by ID.
*/
export const deleteProductApi = async (id: string) => {
return apiRequest(`${BASE_URL}/${id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getCompanyToken()}`,
},
});
};
3. Tanstack Query 활용한 커스텀 훅
이 커스텀 훅들은 Tanstack Query의 useQuery 및 useMutation을 활용하여 API 통합 로직을 추상화하고 최적의 데이터 페칭 및 변이 처리 방식을 제공합니.
// use-products.ts
import { Product } from "@/types/product";
import {
createProductApi,
getAllProductsApi,
getSingleProductApi,
updateProductApi,
deleteProductApi,
} from "@/utils/api/product-api";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
/**
* Hook to fetch all products.
*/
export const useGetAllProducts = () => {
return useQuery({
queryKey: ["products"],
queryFn: getAllProductsApi
});
};
/**
* Hook to fetch a single product by ID.
*/
export const useGetSingleProduct = (id: string) => {
return useQuery({
queryKey: ["product", id],
queryFn: () => getSingleProductApi(id),
enabled: !!id, // Prevents execution if ID is missing
});
};
/**
* Hook to create a new product.
*/
export const useCreateProduct = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (productData: Product) => createProductApi(productData),
onSuccess: () => {
toast.success("✅ Product created successfully!");
queryClient.invalidateQueries({ queryKey: ["products"] }); // Refreshes product list
},
onError: () => {
toast.error("❌ Failed to create product");
},
});
};
/**
* Hook to update an existing product.
*/
export const useUpdateProduct = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
_id,
productData,
}: {
_id: string;
productData: Product;
}) => updateProductApi(_id, productData),
onSuccess: () => {
toast.success("✅ Product updated successfully!");
},
onError: () => {
toast.error("❌ Failed to update product");
},
});
};
/**
* Hook to delete a product by ID.
*/
export const useDeleteProduct = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => deleteProductApi(id),
onSuccess: () => {
toast.success("✅ Product deleted successfully!");
queryClient.invalidateQueries({ queryKey: ["products"] }); // Refreshes product list
},
onError: () => {
toast.error("❌ Failed to delete product");
},
});
};
결론
Tanstack Query는 대규모 제품 데이터 관리의 도전을 해결하기 위한 강력하고 유연한 도구입니다. 이를 통해 비즈니스는 데이터 일관성을 유지하면서도 운영 효율성을 극대화할 수 있습니다. 이 기술을 통해 더욱 효율적이고 효과적인 API 통합을 실현하세요.