dev/프론트엔드

구름톤 유니브 개발로그 : api 모듈화 (react-query 사용기)

wosrn 2024. 4. 2. 17:07

이번 구름톤 프로젝트에서는, api를 모듈화하고 커스텀훅으로 만들어서 사용하였다

 

 

1) apis 폴더 안에 instance.ts 파일에 axios instance를 create해서 만들어둔다 

이때 백엔드 측에서 준 base url은 노출을 막기 위해 env파일에 넣고, gitignore에 넣는다 (이렇게 하면 env파일의 내용이 깃허브에 올라가지 않기 때문에, 협업 프로젝트라면 프론트 팀원들간에 env파일에 변경이 있을 시 따로 알려준다 / vite를 사용한 경우 env파일의 환경변수 이름이 VITE_로 시작해야한다)

 

2) apis 폴더 안에 axios instance를 사용해서 원하는 api 메소드 (get 등) 를 사용하는 코드를 작성한다

(그런데 구글링을 하다보니 async await에서 try-catch를 사용하는 것이 괜찮은 방식인지 좀 더 알아보아야할듯(예외처리는 hooks폴더의 useQuery에서 하는게 나을지) -> 전반적으로 비동기에 대해 좀 더 공부하고,, 위의 고민에 답을 내리면 이부분에 추가를 하겠다)

3) hooks폴더 안에 2에서 만든걸 임포트하여 사용하는 코드파일(커스텀훅)을 만든다

react-query를 사용했고, 데이터에 뭔가 수정을 가할때는 useMutation을, 데이터를 읽기만 할때는 useQuery를 사용하는데 나는 get만 하는거였기 때문에 useQuery를 사용했다

(useQuery에 관해서도.. 제대로 알아본 후 포스팅을 별도로 작성해야겠다)

아무튼 위의 코드에 대해서만 이야기를 하자면, useQuery의 첫 매개변수로 쿼리키를 주고, 두번째 변수로 함수(2에서 만든, api통신의 결과로 promise객체를 반환하는)를 주어 사용했다

 

 

4) 위의 api통신을 사용할 페이지의 코드파일에 작성한 코드들이다 (페이지코드 라고 칭하겠다)

우선 useOtherCollection을 사용하여 리턴받을 객체를 선언해주고, 이 리턴객체를 이용해서 렌더링을 해주었다

 

이부분에서 겪었던 이슈가 있었는데, 이 페이지에서는 첫 렌더링시에 디폴트 옵션값으로 get을 해오고, 그 뒤론 사용자가 옵션을 바꿀때마다(월,최신순/인기순) 그에 따라서 새로 get을 해와야 했었다

초반에는 useOtherCollection코드의 queryKey가 params가 포함되지 않은 ["otherCollection"]이었다

그리곤 바로 위의 페이지코드에서 useEffect의 의존성 배열에 filterOption,presentMonth 등의 state값을 넣어서 이 값들이 변할때마다 data를 갱신하여 렌더링하려고 했으나, 원하는대로 되지 않았다

 

state값이 변경되면 이 페이지의 관련된 컴포넌트들이 재렌더링되는것이지, 이 페이지의 state값이 변경된다고 해서 useOtherCollection에 있는 get요청을 새로 해오는것이 아니기 때문의 위의 문제가 발생했다

즉, state값이 정상적으로 바뀌어도 get요청이 새로 일어나지 않고, 이전에 받아온 data값이 그대로 유지된다

추가로 방금 알게된 것은 , queryKey가 params가 포함되지 않은 ["otherCollection"]인 상태에서 페이지코드의 useEffect의 의존성 배열에 presentMonth를 넣으면, 

1) 해당 페이지를 띄운 상태에서 월을 바꿔서 선택해도 data는 그대로이다 (사진의 윗 부분 - 3월의 data가 그대로 유지됨)

2) 그런데 이때 다른 창을 띄웠다가 이 페이지를 다시 열면, data가 4월의 data로 바뀐다 (4월의 데이터인 빈 데이터로 바뀜)

-> 아마도 다시 이 페이지를 열었을 때 첫 렌더링때처럼 useOtherCollection을 다시 호출하게되고 , 이때의 state값(presentMonth)은 디폴트값이 아닌 바꾼 값(4월)이기때문에, 이 state값으로 data를 가져와서 이런 일이 일어나는듯 하다

 

react-query 캐싱 기능 제대로 이해하기

stale, cacheTime, refetch 되는 조건에 대해 알아보자.

velog.io

 

 

[React Query] 캐싱(feat. refetch)

[react-query] 캐싱(feat. refetch)

velog.io

=> 추가적인 구글링을 통해 조금 더 정확히 알게되었다 ..! react-query가, 데이터가 stale할 때 refetch를 하게되는 경우 중 하나가 브라우저 화면이 다시 focus 됐을 때이기 때문이었다 (데이터가 state하고, 몇가지 조건의 상황 중 하나를 만족하면 refetch를 한다)

즉 queryKey에 params를 포함하지 않고 페이지코드의 useEffect에 params의 값을 넣어봤자 당연히 params값이 바뀌어도 데이터를 refetch하지 않아서 변경한 옵션에 따른 새로운 get이 일어나지 않지만,  다른 탭으로 이동했다가 다시 해당 탭으로 접속했을때 데이터가 사용자가 고른 presentMonth 값에 맞게 새로 refetch되었던 이유는 위의 이유였다

 

 

아무튼 이 문제를 해결하기 위해선 params의 값이 바뀔때마다 (presentMonth,filterOption) useQuery를 호출할 수 있어야 했고, 이를 위해 queryKey에 params를 추가하여 원하는 결과를 얻을 수 있었다 ( presentMonth,filterOption 바뀔때마다 api 호출 새로 일어나서 옵션에 맞는 결과 렌더링)

페이지코드의 useEffect의 의존성 배열엔 data만을 넣어서, useOtherCollection에서 받아온 data의 값이 달라질 때마다 cardData를 새로 map해서 렌더링되도록 했다

 

추가로 디벨롭할 사항 : react-query에 대해 더 이해한 뒤, staletime을 설정하여 react-query의 캐싱기능을 이용하도록,혹은 옵션값들을 커스텀하도록 해볼것 (현재는 staletime을 지정하지 않았기 때문에 디폴트값인 0으로 설정되어, 캐싱을 이용하지 않고 있는 상태이다)

그런데 현재 get받아오는 데이터들이 언제 변경될지 알 수 없는 데이터라 캐싱을 이용하는게 적절할지부터 생각해보긴 해야할듯