노트

쿼리 키 설계와 키 팩토리

Query Key Factory

프런트엔드#react · 연결된 개념 4개

쉽게 말하면

쿼리 키는 '서울시 강남구 역삼동'처럼 넓은 데서 좁은 데로 적는 캐시 주소예요. 키 팩토리로 한곳에서 주소를 만들면 '강남구 전체'나 '역삼동만'처럼 원하는 범위의 캐시만 정확히 무효화할 수 있어요.

비유가 깨지는 곳 주소와 달리 키에 적힌 값은 데이터를 가져오는 함수의 입력이기도 해요. queryFn이 키에 없는 값을 쓰면 다른 데이터가 같은 칸에 섞이니, 인자는 키에서 꺼내 써요.

쿼리 키(Query Key)는 TanStack Query가 캐시 항목을 식별하고 무효화 범위를 고르는 배열이다. 키를 일반적인 것에서 구체적인 것 순서로 쌓고, 한 곳(키 팩토리)에서 만들게 하면 부분 일치(Partial Matching)로 원하는 범위만 정확히 무효화할 수 있다.

const todoKeys = {
  all: ['todos'] as const,
  lists: () => [...todoKeys.all, 'list'] as const,
  list: (filters: string) => [...todoKeys.lists(), { filters }] as const,
  details: () => [...todoKeys.all, 'detail'] as const,
  detail: (id: number) => [...todoKeys.details(), id] as const,
}
 
queryClient.removeQueries({ queryKey: todoKeys.all })        // todo 관련 전부
queryClient.invalidateQueries({ queryKey: todoKeys.lists() }) // 목록만
  • 키는 앞에서부터 부분 일치로 매칭된다. 그래서 ['todos', 'list', …] 구조면 ['todos', 'list']로 모든 목록을 한 번에 고를 수 있다
  • 키 문자열을 여기저기 손으로 쓰면 오타 하나로 무효화가 안 된다. 팩토리는 이 실수를 막는다(매직 넘버와 설명 상수, DRY 원칙)
  • queryFn의 인자는 키에서 꺼낸다. queryFn은 { queryKey }를 받으니 인라인 함수로 값을 다시 넘기지 말고 키에서 읽는다. 키에 넣지 않은 값을 함수가 쓰면 캐시가 섞인다(eslint-plugin-query가 잡아 준다)
const fetchTodos = ({ queryKey: [{ state, sorting }] }) => api.get(`todos/${state}?sort=${sorting}`)
useQuery({ queryKey: [{ scope: 'todos', entity: 'list', state, sorting }], queryFn: fetchTodos })
queryClient.invalidateQueries({ queryKey: [{ entity: 'list' }] }) // 모든 scope의 목록
  • 키 요소를 객체 하나로 만들면 이름으로 꺼낼 수 있고, 객체 부분 일치로 "모든 목록" 같은 범위도 고를 수 있다

전체 개념은 TanStack Query.

출처: TkDodo - Effective React Query Keys: Use Query Key factories · Leveraging the Query Function Context: Object Query Keys

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • useSuspenseQuery

    useSuspenseQuery는 TanStack Query의 결과를 suspense와 에러 경계(Error Boundary)에 맡기는 훅이다. 로딩 중이면 컴포넌트가 suspend되고, 실패하면 에러가 던져진다. 그래서 컴포넌트 안에는 성공한 경우의 코드만 남는다.

  • JPQL과 @Query

    JPQL(Jakarta Persistence Query Language)은 테이블이 아니라 엔티티와 필드를 대상으로 쓰는 JPA의 객체 지향 쿼리 언어다. 실행할 때 연결된 DB의 SQL로 번역된다. Spring Data에서는 @Query로 리포지터리 메서드에 직접 붙인다.

  • useActionState와 폼 액션

    React 19에서는 <form action={함수}>에 함수를 바로 넘길 수 있고, useActionState가 그 액션의 대기 상태와 마지막 결과를 한 훅으로 관리한다. useState + onSubmit + 로딩 플래그로 짜던 패턴을 대체한다.

  • React로 보는 SOLID

    SOLID는 원래 객체 지향 설계 원칙이지만 React 컴포넌트·props·훅에도 그대로 옮겨 볼 수 있다. 원칙 자체보다 "어떤 코드 모양이 되는가"를 짧게 정리한다.

  • Redux 이후의 상태 관리 선택

    한때 React 앱의 기본값이던 Redux는 2025~2026년 기준으로 여러 선택지 중 하나가 됐다. 상태를 종류별로 나눠 각자에 맞는 도구를 고르는 방식이 자리 잡았기 때문이다.

보기 옵션