프로젝트/TYLEGG

불필요한 데이터 요청의 최적화(React-Query or TanstackQuery)

58청춘 2024. 4. 16. 23:11
728x90

문제의 발단은 이러하다.

개발한 컴포넌트에서 필요 이상의 API 요청이 발생하는 것이 문제이다.

 

파악한 문제는 2가지 이며 천천히 문제의 원인과 해결 방법에 대한 설명을 작성하겠다.

 

1. API 요청 방식

이 문제가 가장 근본적인 원인이였다.

기존 코드는 특정 컴포넌트를 클릭하면 그 컴포넌트에 맞는 데이터를 요청하는 방식으로 설계했다.

 

그로인해 같은 데이터라도 다시 다른 컴포넌트를 클릭했다가 과거의 컴포넌트를 눌러도 같은 API 요청이 발생하게 된다.

이러한 방식은 다른 프로젝트나 컴포넌트 개발시 큰 데이터 혹은 서버의 상태에 따라 원활한 서비스 제공이 어려울 것이라 판단했다.

 

이 문제는 각각 API 요청을 하던 로직을 초기 렌더링시 다수의 데이터를 병렬로 요청해 처리하도록 했다.

 

기존 코드

// 해당 API는 컴포넌트의 클릭 이벤트를 감지할 때마다 동작하는 API
const testApi = async (position: string) => {
  const response = (await axios.get(`/champions/${position}`)).data;
  return response;
};

 

새로 설계한 코드

const info = useQueries(
  ePositions.map(position => ({
    queryKey: ['image', position],
    queryFn: async () => {
      const response = (await axios.get(`/champions/${position}`)).data;
      return response["champions"];
    },
  }))
);

 

2. 브라우저 focus에 의한 API 요청

이 문제는 보고있던 브라우저 창에서 다른 브라우저로 갔다가 다시 원래 브라우저로 돌아올 때 focus가 잡히며 refech되어 불필요한 요청이 발생하는 문제였다.

 

이 문제는 useQueries의 refetchOnWindowFocus 옵션을 "false"로 설정해 비활성화 할 수 있었다.

const operatorImgData = useQueries({
  queries: ePositions.map((position, idx) => ({
    queryKey: [`image${idx}`, position],
    queryFn: async () => getOperatorImgDataApi(position),
    refetchOnWindowFocus: false, // 브라우저 창 포커스에 따른 자동 재요청 비활성화
    gcTime: 1000 * 60 * 5,  // query client에서 캐시된 데이터가 5분뒤에 삭제되도록 설정
    staleTime: 1000 * 60 * 5,    // 최초 호출 후  staleTime을 5분로로 설정
  })),
  combine: (result) => {
    return ({
      data: result.map(res => res.data),
      isLoading: result.map(res => res.isLoading)
    })
  }
});

 

728x90