next js 12 React Query 회고

이명진·2024년 1월 31일
0

회고록

목록 보기
10/10

react Query 를 프로젝트에 적용하게 되었다. 적용하게 된 이유에 대해서는 이전글에서 정리하게 되었다.

오늘은 사용 법 간단하게 작성하고 회고를 작성한다.

사용법

사용 법은 간단하다. 이전에 사용해본 경험이 있어서 빠르게 적응할수 있었다.
이전 글에는 설치까지 알아봤는데 코드에서 사용하는 방법을 작성해본다.

이전글 : next js 12 React Query 세팅

_app.ts

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

return (
  <QueryClientProvider client={queryClient}>
	<app/>
 </QueryClientProvider>
 )

이렇게 감싸준다.

v5변경점

이전 사용법과 다르게 v5 는 변경 사항들이 생겼는데 처음에는 쭉 읽다가 어려웠는데 쓰다보니 적응도 되고 이해도 차차 되었다.

사용에 관해서 이전 버전에서는 useQuery 를 사용하면 매개변수로 각각 받아서 사용했다.

예) useQuery(key, fn, options)
이런식으로 순서대로 사용하면 되었는데 v5에서는 객체로 받도록 수정이 되었다. 

useQuery({ queryKey, queryFn, ...options })

확실히 이렇게 변경된 점이 이해하는것에서는 수월했다.

queryKey 로 캐싱하는 값들을 키값을 매겨서 가지고 있는다.

queryFn는 함수로 axios나 fetch함수를 사용한다.
options는 다양한 옵션들이 있다.

보통 훅스 형태로 사용했는데 캡슐화 처럼 사용해서 관심사를 분리시킬수 있어서 좋았다.

예시 ) useQuery.ts

const fetchData = async (cardSeq: number) => {
  return await axios<axiosDetailDataType>(
    `${process.env.NEXT_PUBLIC_API_KEY}/GetDetail/${cardSeq}`,
    { headers }
  ).then(({ data }) => data);
};

export const useGetDetail = (cardSeq: number) => {
  return useQuery({
    queryKey: ['detailBody', cardSeq], // cardSeq를 키값으로 받아서 저장한다. 
    queryFn: () => fetchData(cardSeq), // 위의 함수 fetch호출한다. 
    placeholderData: keepPreviousData, // 이전데이터를 가지고있는 옵션
    staleTime: 300000, // 어느정도 까지 신선도를 체크하는가 , stale이 된 데이터는 제거된다. 300000을 옵션으로 주었다. 
    throwOnError: true, // 에러 던지는것 
    enabled: !!cardSeq, // cardSeq가 있을때 이 query가 감시한다. 
    select: data => { // 서버에서 받은 데이터를 가공해서 사용할수 있다. 
      const { List, DetailList } = data;
      let obj = {
        staticData: makeStaticDetail(data),
        contentsList,
       DetailList,
      };
      return obj;
    },
  });
};

v5 변경점은 useQuery에서 onSuccess, onError, onSettled 콜백들은 이제 사용되지 않는다는 것이다. 대신 위에 사용한것처럼 throwOnError를 사용할수 있다.
또한 keepPreviousData 옵션과 isPreviousData는 placeholderData 옵션과 isPlaceholderData로 변경되었다.


import {
2   useQuery,
3+  keepPreviousData
4} from "@tanstack/react-query";
5
6const {
7   data,
8-  isPreviousData,
9+  isPlaceholderData,
10} = useQuery({
11  queryKey,
12  queryFn,
13- keepPreviousData: true,
14+ placeholderData: keepPreviousData
15});

Mutation 활용

예시 ) useQuery.ts

export const useUpdateStatic = (onSuccess: () => void, onError: () => void) => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async ({ body, urlOption, method }: useOnSavePropsType) =>
      await axios({
        url: `${process.env.NEXT_PUBLIC_API_KEY}/detail/${urlOption}`,
        method: method,
        data: body,
        headers,
      }),
    onError,
    onSuccess,
    onSettled: async () => { // 이부분으로 무효화를 진행하여서 업데이트 시킨다. 
      return queryClient.invalidateQueries({
        queryKey: ['detailBody'],
      });
    },
  });
};

useMutation도 처음에는 조금 어려웠는데 사용하다보니 익숙해졌다.
훅스로 사용해서 onSuccess, onError 를 파라메터로 받아서 활용했다.

코드 내부에서 활용하면 굳이 안넘겨 줘도 되는데 훅스로 만들어서 파라메터를 받도록 하였다.

코드 에서 훅스 사용법은

// index.ts
const {mutation} = useUpdateStatic(onSuccess,onError) //훅스를 import해서 구조분해할당을한다. 

mutation(파라메터) // mutationFn에서 선언한 파라메터들을 던져 주면 된다. 

이외에도 구조분해 할당에서 isError, isSuccess , Error 값을 도출해 낼수 있는데

isError 는 에러인지 아닌지, isSuccess는 성공인지 아닌지 Boolean값을 얻을수 있다.

근데 이것 사용하는것보다 자체로 훅스로 파라메터를 넘겨서 성공 함수, 실패함수 를 넘겨주는것이 더 좋다.

error 는 객체형태로 Error interface를 사용한다. error.message 로 message를 찍어볼수 있다.

회고

react Query를 사용하니 코드를 확실히 많이 줄일수 있었다. 이것은 코드를 분리해서 많이 줄인것도 추가다.

기존에는 400줄정도 였는데 분리시키고 react Query를 사용해보니 100줄로 줄일수 있었다.

이전글에서 작성했지만 useEffect코드 도 줄이고 훅스를 사용해서 코드를 줄일수 있었다.

이미지를 보면 왼쪽이 이전 코드 오른쪽이 리팩토링 코드 이다.

근데 컴포넌트도 많이 분리되어서 컴포넌트들을 다합치면 비슷하긴 하다.

추가로 관심사를 많이 줄일수 있었다. 데이터를 추가하고 업데이트 할때마다
url파라미터로 관리하거나, useEffect 로 변화된 정보가 있으면 리렌더링을 해줬는데

react-Query mutation을 활용한 결과 매끄럽게 관리할수 있었다. 덤으로 loading정보를 알수 있어서 로딩중.. 이란 값을 전달 해줘서 UX상으로 효과적으로 변화되었다고 생각이 든다.

불편했던 점이라면 카드형식이라서 부모(카드 리스트) , 자식 (카드 디테일) 둘다 react-query를 2개 사용해서 관심사를 분리시켜줬는데 변경할때마다 mutation을 관리해줘야 해서 불편하긴 했다. 원래는 하나의 함수를 돌려쓸수 있는데 어느부분에서는 부모의 값을 변경해주는 mutation을 사용해야 하고 어느부분에서는 자식의 값을 변경해주는 mutation을 사용해야 해서 코드 중복이 조금 추가 되었다고 해야하나 (?) 이것은 내가 아직 부족해서 생긴 문제일거라고 생각이 든다.
그래도 관심사를 두개로 분리해서 유지보수와 코드 파악 부분에서는 매끄러워 졌다.

거의 기존의 코드를 엎고 새로 만드는 노력을 들여서 다시 개발해야 했지만 성능상 ,UX 상 이점이 큰것 같다.

프로젝트 중간에 react-query를 도입하게 되어서 이전 다른 부분들에서도 차차 적용해야 할것 같다.

일단 하나의 프로젝트로 리펙토링한것의 회고를 남겨본다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글