1. react-query V5 마이그레이션에 대한 고민
현재 우리가 사용중인 react-query는 v4이다. sentry를 사용하려는데, 버전 5에서 duplicated되었다면서 logger 코드를 제거하라고 한다. 그리고 기존에는 @suspensive/react-query의 useSuspensiveQuery를 사용하여 useQuery에서 제공하는 data의 값의 undefined타입을 제거해서 분기처리 없이 사용했다. 그런데 react-query 5로 버전이 업그레이드 되며 useSuspensiveQuery를 공식적으로 지원한다는 것이다. 이러한 소식에 솔깃했다. react-query를 사용하기 더 편해진 것이 아닐까?
1. V5에서 바뀐 것에는 어떤 게 또 있을까?
주요한 변화만 작성해보자.
-
각 쿼리 훅의의 인자가 객체 형태로 모두 바뀌었다.
-
기존 cacheTime → gcTime으로 변경 (garbase collect의 약자)
-
useQuery에서 onSuccess, onError, onSettle 제거 : 예측 가능하고 일관성을 위해
- onError → Error Boundary로 에러 처리
- mutation에서의 콜백은 그대로 유지된다.
-
낙관적 업데이트 간소화 :
variables사용const queryInfo = useTodos() const addTodoMutation = useMutation({ mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }), onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) if (queryInfo.data) { return ( <ul> {queryInfo.data.items.map((todo) => ( <li key={todo.id}>{todo.text}</li> ))} {addTodoMutation.isPending && ( <li key={String(addTodoMutation.submittedAt)} style={{ opacity: 0.5 }}> {addTodoMutation.variables} </li> )} </ul> ) } -
useMutationState로 mutation상태 공유
-
infinite query에서도 prefetch
-
Hydrate컴포넌트 → HydrationBoundary
-
loading → pending, isLoading → isPending
-
useRrorBoundary → throwOnError
-
서버에서 retry 횟수 3 → 0
2. 팀원과 논의
혼자서 결정하기에는 변경 사항이 너무나 많았다.
우선, V5로 바꾸고 싶은 이유와 바꾸지 않아야 할 이유를 혼자서 생각해보았다.
1. V5로 바꾸고 싶은 이유
@suspensive/query가 불필요하다- 공식적으로 지원해주기에 기존
@suspensive/query를 제거해도 된다.
- 공식적으로 지원해주기에 기존
- 최신 트랜드를 따라가고 싶다
- 무조건 트랜드를 쫓는 것은 올바르지 않다고 생각하지만, 마음 한 구석에서 최신 트랜드를 쫓고 싶은 것은 어쩔 수 없는 듯하다.
- 낙관적 업데이트의 간소화로 인해 코드 및 추후 리소스 감소
- infitniteQuery에서도 prefetch가 된다.
- 추후 계속된 react-query의 지원을 받기 위해서는 최신 버전으로의 업그레이드가 필요하다.
2. V5로 바꾸지 말아야 할 이유
- 마이그레이션을 수행할 팀원들의 리소스
3. 팀원과 논의
변경사항이 정말 많다. 이에 대한 리소스는 전부 프론트엔드 팀원들의 몫이기 때문에 팀원과의 논의는 필수적이다. 내가 작성한 이 노션 페이지를 팀원에게 공유하며 팀원의 의견을 물었다.
내용을 정리하자면 기존 @suspensive/react-query도 현재 V2를 준비 중이고, 불안정하다. 또한, react-query에서도 기존 useQuery의 데이터 undefined처리를 위해 useSuspenseQuery를 V5에서 도입했기에 우리가 추구하던 방향과 같다고 생각했다.
2. react-query V5로 마이그레이션
마이그레이션 방법[팀원 공유용]
1. single singature → one object
-
Before
import { useSuspenseQuery } from '@suspensive/react-query'; export const useGetNotifications = () => useSuspenseQuery(Keys.getNotifications(), getNotification, {onSuccess:() => {}});@suspensive/react-query→@tanstack/react-query로 교체한다.
- 기존 일반 인자로 넘기던 것을 object형태로 변환한다.
- 옵션이 있다면 object를 벗긴다.
- useSuspenseQuery에서 onSuccess, enable옵션은 V5에서 제거되었습니다. onSuccess는 useQuery를 사용하는 측에서 onSuccess를 return받아 사용해야합니다. enable옵션을 사용하기 위해서는 useQuery를 사용해야 합니다.
- useSuspenseQuery는 enabled, suspense가 모두 true로 자동설정됩니다. 즉, useSuspenseQuery를 상요하여 특정 조건에 따라 실행하는 것은 불가능합니다.
-
After
import { useSuspenseQuery } from '@tanstack/react-query'; export const useGetNotifications = () => useSuspenseQuery({ queryKey: Keys.getNotifications(), queryFn: getNotification, onSuccess:() => {} });useSuspensiveQuery는 위와같이 queryKey, queryFn, useSuspensiveMutation은 동일한 방식으로 mutationFn으로 객체를 생성하면 됩니다.
2. 기존 Hydrate → HydrationBoundary로 교체
3. cacheTime → gcTime
4. useSuspenseQuery의 enabled옵션을 사용아는 경우
enabled옵션은, enabled가 true인 경우 데이터를 요청하는 것이다. 그런데, useSuspenseQuery의 경우 enable옵션이 제거가 되었다. 해결 방안은 다음과 같다.
- useSuspenseQuery → useQuery로 교체 한다.
- useQuery에는 enable옵션이 여전히 존재하기에 훅만 교체하면 된다.
- enabled옵션을 제거한다.
- enabled옵션을 제거할 경우, useSuspenseQuery는 suspense옵션이 항상 true이므로 해당 훅을 Suspense로 감싸야 한다.
- e.g. 학교 검색
-
기존 방식
<SchoolForm />SchoolForm에 입력 컴포넌트와 결과 컴포넌트가 모두 존재했다.
-
- 수정한 방식
<SchoolInput />
<Suspense fallback={<Loading />}>
<SchoolResultList />
</Suspense>
입력 컴포넌트와 결과 컴포넌트를 분리하고, 결과 컴포넌트에서 데이터를 요청하기에 Suspense로 감싸서 로딩화면을 명시하였다.
5. useInfiniteQuery
initialPageParam 프로퍼티를 추가하면 된다.
6. loading → pending, isLoading, isPending
결론
react-error-boundary의 github을 보았을 때 130여 줄 밖에 되지 않는다.
마이그레이션 체크리스트
-
profile
-
grouping
-
auth
-
meeting
-
Hydration컴포넌트
-
해결해야할 것
initialPage를 넘겨주었다.
-
-
onSuccess, enabled 등 duplicated된 옵션에 대한 해결책
-
infinityQuery → 타입 에러
3. tanstack/react-query V5로 바꾼 후기
1. 좋았던 점
-
devtool의 많은 기능 지원
보기만해도 시원하네요
UI도 깔끔해지고, 정렬 등 기능도 많아졌습니다.
2. 마이그레이션 팁
- 마이그레이션 이전에, 리소스가 얼마나 소요될 지와, 이러한 리소스를 들여서 마이그레이션할 만한 충분한 이유가 있는지 팀원과 논의한다.
- 만약 마이그레이션을 하기로 결정했다면,
- 버전 이전과 이후의 차이점에 대해 인지한다.
- 우리 프로젝트에서는 버전 변경 사항에 대해 어떤 코드를 변경을 해야하는지 작성한다.
- 하나하나 마이그레이션을 수행한다.