사실 Front-End를 맡아, 나의 장점으로는 페이지를 만드는 것이다. 하지만 단지 페이지만 만들거면 그냥 HTML 기계를 쓰면 되지 않는가? 그렇다! Front의 꽃은 다시 돌고 돌아, Back에서 받아온 데이터에 대한 상태를 관리하는 것이라고 생각하게 되었다. 하지만 이번 십장생 프로젝트에서 사용한 상태 관리 Tool인 React-Query와 Zustand는 나도 아직까지도 이해를 못한 지경이기 때문에, 프로젝트가 끝나고 잠시 여유로운 지금 이에 대한 정리가 필요하다고 느꼈다.
먼저 react-query의 사용 절차에 대해서 이야기해 볼 필요가 있다.
- 설치 코드
npm install @tanstack/react-query
yarn add @tanstack/react-query
- React-Query 설정
React-Query는 QueryClinet를 통해 관리된다. 이를 통해 캐시, 네트워크 요청 및 기타 설정을 관리
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* 나머지 앱 컴포넌트 */}
</QueryClientProvider>
);
}
- 데이터 가져오기 함수 생성 - 이 함수는 , 비동기적으로 데이터를 요청하고 응답을 반환
async function fetchPosts() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
}
- useQuery 사용하여 데이터 로딩
- useQuery 훅을 사용하여, Component에서 server 데이터를 요청하고, 로딩 상태, 데이터, 오류 상태를 관리
import { useQuery } from '@tanstack/react-query';
function Posts() {
const { data, error, isLoading } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>An error has occurred: {error.message}</div>;
return (
<div>
{data.map(post => (
<p key={post.id}>{post.title}</p>
))}
</div>
);
}
위 과정들을 통해서 React-Query는 서버 상태를 비동기적으로 가져오고, 캐싱하고, 동기화하고, 업데이트하는 복잡성을 추상화해준다.
장점
1. 복잡성 감소 : 데이터 캐싱, 패칭과 같은 작업들을 추상화함으로, 로직과 인터페이스에 집중 가능
2. 코드 재사용성 향상 : 비동기 데이터 관리 로직을 라이브러리가 처리하게 하기 때문에 재사용성이 향상 -> 유지보수와 확장성 측면에서 장점
3. 성능 최적화 : 불필요한 네트워크 요청을 줄이고 사용자에게 더 빠른 응답시간 제공
4. 상태 관리의 단순화
-> 이러한 장점들은 결국 개선된 사용자 경험을 불러온다.
마지막으로 예시 코드를 기반으로 한 줄씩 설명을 이어나가본다. 프로젝트 상황에서, 상태코드 테이블을 기반으로 몇가지의 공통 코드들을 불러올 필요가 있었다. 이러한 상황에서, 코드를 불러오는 React-Query 기반 훅이 필요했었다.
import { useQuery } from "@tanstack/react-query";
import { axiosInstance } from "../apis/lib/axios";
const fetchMultipleDetailCodes = async (codeTypes: string[]) => {
const requests = codeTypes.map((codeType) =>
axiosInstance.get(`/codes/details/${codeType}`).then(res => res.data.data)
);
// 비동기 요청을 병렬로 실행
return Promise.all(requests);
};
export const useMultipleDetailCodes = (codeTypes: string[]) => {
return useQuery({
queryKey: ['detailCodes', ...codeTypes],
queryFn: () => fetchMultipleDetailCodes(codeTypes),
});
};
// 사용 예시 구문
// const { data: multipleDetailCodesData} = useMultipleDetailCodes(["KPT", "AnotherType"]);
const fetchMultipleDetailCodes = async (codeTypes: string[]) => {
const requests = codeTypes.map((codeType) =>
axiosInstance.get(`/codes/details/${codeType}`).then(res => res.data.data)
);
// 비동기 요청을 병렬로 실행
return Promise.all(requests);
};
export const useMultipleDetailCodes = (codeTypes: string[]) => {
return useQuery({
queryKey: ['detailCodes', ...codeTypes],
queryFn: () => fetchMultipleDetailCodes(codeTypes),
});
내가 개인적으로 생각했을 때 react-query는 Java의 메소드와 같다고 생각을 했음. react-Query와 zustand에 친해지는 것이 이번 프로젝트의 개인적인 목표!