React Query의 queryKey, 어떻게 잘 써야 할까?

JungHoon Park·2025년 6월 22일
0

front-end

목록 보기
1/1
post-thumbnail

React Query는 서버 상태를 쉽게 관리할 수 있도록 도와주는 라이브러리입니다.
API 요청 결과를 캐싱하고, 자동으로 동기화도 해주니까 정말 편리하죠.

하지만 이 모든 기능의 중심에는 queryKey가 있다는 사실, 알고 계셨나요?
이번 글에서는 queryKey가 왜 중요한지, 그리고 실무에서 어떻게 효과적으로 관리하면 좋을지 이야기해보려고 해요.


queryKey가 중요한 이유

React Query는 내부적으로 queryKey를 기준으로 데이터를 구분해요.

  • 키가 같으면 같은 데이터를 보고,
  • 키가 다르면 완전히 새로운 데이터로 인식합니다.

즉, queryKey는 캐싱, 무효화, refetch의 기준이 됩니다.
그래서 신중하게 설계하는 게 정말 중요해요.


어떤 queryKey가 좋은 key일까?

1. 명확하고 고유하게

어떤 데이터를 가져오는지 한눈에 알 수 있어야 해요.

['todos', userId]
['users', userId]

키만 봐도 "아, 이건 userId로 특정한 todos나 users 데이터를 가져오는구나"라고 알 수 있죠.


2. 객체의 순서를 항상 고정하기

React Query는 내부적으로 JSON.stringify를 이용해서 키를 비교하는데요,
객체 안의 속성 순서가 다르면 다른 키로 인식돼요.

['posts', { authorId: 5, page: 1 }] // ✅ OK
['posts', { page: 1, authorId: 5 }] // ❌ 완전히 다른 키로 처리됨

따라서 queryKey에 객체를 넣을 때는 속성 순서를 일관되게 유지해야 합니다.


3. 계층 구조는 배열로 표현하기

복잡한 데이터는 배열로 표현하는 게 좋아요.
예를 들어, 유저의 게시글을 가져오는 경우에는 다음처럼요:

['users', userId, 'posts']

중첩된 관계를 명확하게 보여줄 수 있어서 나중에 invalidate나 refetch할 때도 유용합니다.


queryKey 팩토리 함수로 관리하기

쿼리가 많아지면 키를 실수하기도 쉽고, 일관성도 깨질 수 있어요.
그래서 저는 보통 queryKey를 함수로 만들어서 관리합니다.

// queryKeys.ts
export const queryKeys = {
  all: ['todos'],
  lists: () => [...queryKeys.all, 'list'],
  list: (filters) => [...queryKeys.lists(), { filters }],
  details: () => [...queryKeys.all, 'detail'],
  detail: (id) => [...queryKeys.details(), id],
};

이런 식으로 팩토리 함수를 만들어두면,

  • 오타를 줄일 수 있고
  • 자동완성도 되고
  • invalidate할 때도 간편해요

invalidateQueries는 정확하게 써주기

예를 들어 어떤 필터로 리스트를 가져오고 있었다면, 해당 필터에 맞는 리스트만 invalidate하는 게 좋겠죠?

queryClient.invalidateQueries(queryKeys.list({ filter: 'active' }));

괜히 ['todos']처럼 뭉뚱그려 invalidate하면 캐시가 다 날아가버릴 수 있어요.
불필요한 리패치 방지를 위해서라도 정확한 queryKey를 사용하는 게 중요합니다.


조건부 쿼리에는 null과 enabled를 같이 쓰자

userId가 있을 때만 유저 정보를 가져오고 싶다면? 아래처럼 처리할 수 있어요.

const queryKey = userId ? ['user', userId] : null;

useQuery({
  queryKey,
  queryFn: fetchUser,
  enabled: !!queryKey,
});

이렇게 하면 userId가 없을 땐 쿼리를 아예 실행하지 않아서,
불필요한 요청이나 ['user', undefined] 같은 애매한 캐시 키도 방지할 수 있습니다.


정리

queryKey 잘 쓰는 법, 요약하면 이렇게 정리할 수 있어요 👇

  • 명확하고 구체적인 key를 만든다
  • 객체를 쓸 땐 속성 순서를 항상 고정한다
  • 계층 구조는 배열로 표현한다
  • 반복되는 key는 팩토리 함수로 관리한다
  • 조건부 쿼리는 null과 enabled를 활용한다

참고 링크

profile
이사중 ! https://dpark-log.tistory.com/14

1개의 댓글

comment-user-thumbnail
2025년 6월 26일

안녕하세요 좋은 글 잘읽었습니다!
다만 '2. 객체의 순서를 항상 고정하기' 부분에서 잘못된 예시가 있는 것 같아 댓글 남깁니다.

['posts', { authorId: 5, page: 1 }] // ✅ OK
['posts', { page: 1, authorId: 5 }] // ❌ 완전히 다른 키로 처리됨

이렇게 예시를 들어주셨는데 {authorId: 5, page: 1} 객체 내부의 순서는 쿼리 키 비교 시 무의미한 것으로 알고있습니다. json직렬화를 하지만 내부적으로 객체의 순서를 정렬한다고 합니다.

https://tanstack.com/query/latest/docs/framework/react/guides/query-keys#query-keys-are-hashed-deterministically

https://stackoverflow.com/questions/73295707/how-does-reactquery-monitor-complex-query-key-changes-by-value-and-or-reference?utm_source=chatgpt.com
위 문서를 확인해주시면 감사하겠습니다 :)

답글 달기