react-query는 데이터 패칭과 상태 관리를 간편하게 처리할 수 있게 해주는 정말 좋은 라이브러리이다.
이번 프로젝트에서도 react-query를 이용한 데이터 패칭을 하게되어서 열심히 사용해보고 있다.
현재 진행하는 프로젝트는 다른 분과 함께하다보니, 그 분이 특정 query-key를 통해서 데이터 패칭을 하고 있다면, 나는 그 쿼리를 무효화할 때 그 분이 어떤 query-key를 쓰고 계시는 지 열심히 찾아서 주워야하는 불편함이 있었다. like 헨젤과 그레텔...
이 뿐만 아니라 query-key를 변경해줘야 할 때도 그 쿼리 키를 사용하는 곳을 여기저기 돌아다니면서 query-key를 변경해줘야 하는 끔찍한 경험이 나를 기다리고 있었다.
(쿼리 키만 바꿨을 뿐인데 늘어나는 파일 체인지...)
그래서 query-key-factory를 사용하여 query-key를 한 곳에서 일괄적으로 관리하고, 확인할 수 있게 해야겠다는 생각이 들었다.
query-key-factory가 뭔데?
query-key-factory는 React Query에서 쿼리 키를 생성하는 유틸리티이다.
query-key-factory를 사용하면 쿼리 키를 체계적으로 관리하고 키 생성 로직을 중앙 집중화하여 일관되게 쿼리 키를 사용할 수 있다.
또한, IDE의 자동 완성 기능을 활용할 수 있고, TypeScript와 함께 사용하면 타입 안정성까지 보장할 수 있다.
(실제로 사용해봤을 때 이게 체감이 가장 컸다 ! 오타로 인한 휴먼 에러도 발생하지 않는 것은 덤 )
그리고 무엇보다도 동일한 쿼리 키를 여러 곳에서 재사용할 수 있기 때문에 코드의 중복을 줄이고 코드의 일관성을 유지할 수 있다. 동일한 키를 재사용하기 때문에 쿼리 키가 변경되더라도 이를 사용하는 곳에서 추가적으로 코드 수정을 해주지 않아도 되기 때문에 유지보수성도 향상된다.
+ 더 이상 쿼리 키 주우러 여러 파일을 돌아다니지 않아도 된다는 사실 !
이제 query-key-factory가 뭔지, 왜 사용하는지도 알게되었으니 본격적으로 도입해보자
query-key-factory 설치하기
$ npm i @lukemorales/query-key-factory
# or
$ pnpm add @lukemorales/query-key-factory
# or
$ yarn add @lukemorales/query-key-factory
query-key 정의하기
나는 아래 표처럼 관심사를 나눈 후 query-key를 정의해주려고 한다.
가장 많은 api 함수를 관리할 dashboard를 예시로 query-key를 정의하여 사용해보자
dashboard | card | column | comments | user |
list | list | list | list | invitations |
detail | detail | current | ||
invitations | ||||
members |
사용법은 생각보다 간단하다. `.ts` 파일을 생성한 후 아래와 같이 정의해주면 된다.
// dashboardQueryKeys.ts
const dashboardQueryKeys = createQueryKeys("dashboard", {
list: (props: DashboardListSearch) => ({
queryKey: ["dashboardList"],
queryFn: async () => await getDashboards(props),
}),
detail: (dashboardId: number) => ({
queryKey: ["dashboardDetail", dashboardId],
queryFn: async () => await getDashboardDetails(dashboardId),
}),
invitations: (dashboardId: number, props: DashboardInvitation) => ({
queryKey: ["dashboardInvitations", dashboardId],
queryFn: async () => await getDashboardInvitations(dashboardId, props),
}),
members: (props: MembersSearch) => ({
queryKey: ["dashboardMembers", props.dashboardId],
queryFn: async () => await getMembers(props),
}),
});
export default dashboardQueryKeys
본인이 사용하는 api함수를 설명할 수 있는 키워드를 골라서 정의해주면 된다. 이렇게 정의하는 과정은 끝났으니 이제는 사용해볼 시간이다 !
함수를 호출하고 싶을 때는 useQuery안에서 원하는 함수를 QueryKeys를 import하여 넣어주면 된다.
const Components = ({ dashboardId }: { dashboardId: number }) => {
const { data } = useQuery(dashboardQueryKeys.detail(dashboardId));
return <div>{data}</div>
};
mutation을 사용한 후, 특정 쿼리를 무효화 시켜주고 싶다면 정의한 QueryKeys를 import해서 무효화할 queryKey 위치에 넣어주면 된다.
const Compponents = ({ dashboardId }: { dashboardId: number }) => {
const queryClient = useQueryClient();
const dashboardQuery = dashboardQueryKeys.detail(dashboardId);
const mutation = useMutation({
mutationFn: async () => await apiFetching(props),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: dashboardQuery.queryKey });
},
});
return <div>예시<div>
};
개선점
앞서 query-key-factory를 왜 쓰는지 알아본 것처럼, 유지보수하는 데 있어서 훨씬훨씬 개선되었다는 것을 온몸으로 느낀다.
구현 과정에서 해당 쿼리를 무효화할 때도 쿼리 키를 어디서 찾아야하는지 명확하기 때문에 찾기도 쉽고, queryFn도 미리 파일 안에서 정의해주었기 때문에 동일한 query함수를 사용할 때 반복해주지 않아도 되었다.
반복되는 코드가 줄어들자 자연스럽게 코드의 길이도 줄고 가독성도 향상되는게 눈으로 보였고, 수치상으로 비교한다면 꽤나 의미있는 수치가 되지 않을까 기대된다.
프로젝트 전반에 적용한 후 개선 정도를 비교해보려고 한다.
혹시 react-query를 사용하고 있다면 꼭 한 번 query-key-factory를 도입해보길 추천한다.
그럼 오늘은 이만 ~!
안뇽 !
'🗂️ 개발 이모저모' 카테고리의 다른 글
OAuth 과정을 알아보겠습니다 (with. 카카오) (4) | 2024.09.15 |
---|---|
내 이미지 어디갔어 !? (배포환경에서 svg 이미지가 로드되지 않는 이유) (5) | 2024.09.12 |
[FeedB] 무한 스크롤 구현 (with. App router & react-query) (0) | 2024.07.26 |
[FeedB] invalidateQueries가 동작하지 않았던 이유 (with. NextJS) (0) | 2024.07.05 |
[FeedB] 기획 소개 및 컨벤션 (feat.구현계획) (0) | 2024.06.17 |