엘리스 3차 팀프로젝트에서 처음으로 React Query를 사용해보았습니다. 당시에는 React Query에 대해 잘알지 못하였고 그냥 단순히 'React Query를 사용하면 좋다, useState를 사용하지 않고도 서버로부터 fetching 받은 데이터를 화면에 바로 바로 뿌려줄 수 있다.' 정도만 이해하고 프로젝트를 진행하였습니다. 때문에 React Query 단편적인 기능만 사용해보았습니다.
다음 개인 프로젝트에선 React Query의 장점을 이해하고 제대로 사용하기 위해 React Query에 대해 공부해보았습니다.
따로 useState 없이 사용할 수 있다는 장점만 생각하고 사용...
const MainPage = () => {
const stepImages = [step_0, step_1, step_2, step_3];
const stepText = [
"전기차 추천 과정이 준비되어있어요 :)",
"현재 차량을 등록해주셨네요! :)",
"성향 테스트를 완료해주셨네요! :)",
"전기차 추천 결과를 확인해주세요 :)",
];
const navigate = useNavigate();
const [isChatbotOpen, setChatbotOpen] = useState(false);
const user = useQuery("user", UserApi.currentUserGet)?.data?.data;
const step = useQuery("step", StepApi.getStepInfo)?.data?.data?.step;
const { mutate, isLoading, data } = useMutation("step", (data: string) =>
StepApi.postStepInfo(data),
);
공식문서에선 리액트 쿼리를 아래와 같이 간단하게 설명합니다.
React Query is often described as the missing data-fetching library for React, but in more technical terms, it makes fetching, caching, synchronizing and updating server state in your React applications a breeze.
즉, React용 경량 데이터 가져오기 및 관리 솔루션을 제공하는 라이브러리이며 리액트에서 동적 데이터를 빠르고 쉽게 가져오고, 캐싱하고, 업데이트할 수 있도록 최적화해줍니다.
예전 개인 프로젝트에서 state를 통합해서 관리하기 위해서 리덕스, 리덕스 사가를 사용한 경험이 있습니다.
state의 상태를 저장하기 위한 state로 isㅁㅁㅁLoading, isㅁㅁㅁError 등을 반복적으로 선언하고 사용하였고 반복되는 코드 때문에 전체 코드가 매우 길어지고 한눈에 보기 어렵다는 단점을 느낄 수 있었습니다.(+리덕스+리덕스 사가 보일러 코드가 많아서 한눈에 코드를 파악하기 어려웠습니다...)
리액트 쿼리를 사용하면 이 불편함을 줄일 수 있습니다.
리액트 쿼리는 React용 데이터 가져오기 및 관리 솔루션을 제공하는 라이브러리입니다. 리액트 쿼리를 확실히 알기 위해 서버에서 가져온 데이터 관리 즉 상태관리에 대해 자세히 알아야 합니다.
웹 프로그램이 복잡해짐에 따라 상태관리 영역이 단순 클라이언트 상태만 관리하던것에서 서버 값을 저장하고 관리하는데까지 확장되었습니다.
서버 값을 저장하기 때문에 api 통신 관련 코드가 store에서 사용되고 isLoading, isError, isFetching 등 Server State의 상태를 나타내는 변수를 반복적인 선언, 사용하게 되었습니다. 추가적으로 비슷한 구조의 api 통신 코드를 반복적으로 적을 필요가 생겼습니다.
웹 프로그램이 발전함에 따라 Server State의 개념이 탄생하였고 Client State와 Server State로 나뉘게 되었습니다. 이때 Client State와 Server State는 소유권이 누구에게 있는가로 구분 가능합니다.
정리하자면 mvc 패턴이든 flux 패턴이든 웹 프로그램을 제작하면 서버에서 받아온 값(Server State)을 클라이언트에 복제해서 하게됩니다. 이때 서버에 저장된 값은 클라이언트에서 관리하지 못하고 api 요청을 통해 서버에서 관리 됩니다. 즉 api 요청없이 클라이언트에서 아무리 값을 변경해봤자 복제된 값을 변경하는것으로 Server State에 영향을 주지 못합니다.
const result = useQuery({
queryKey,()=>fetch('~~~').then(res=>res.json())
})
const mutation = useMutation(newTodo => {
return axios.post('/todos', newTodo)
})
React Query Hooks에 staleTime, cacheTime, refreshOnWindowFocus, refreshOnMount 등 많은 option이 존재합니다.
cacheTime이 기본값이 5분이기 때문에 따로 옵션을 설정하지 않아도 리액트 쿼리에서 캐싱 기능을 사용하게 됩니다.
Query Client 내부적으로 context 사용하기 때문에 만약 서로 다른 컴포넌트에서 같은 Server State를 fetching해도 중복 호출되지 않습니다. (캐시에 담긴 값 사용)