[Tanstack Query] 6. 쿼리 병합과 의존성 관리

임승민·2025년 2월 16일
0

Tanstack Query

목록 보기
6/9
post-thumbnail

1. 쿼리 실행 조건과 의존성 관리 : queryKey, enabled

queryKey와 enabled를 사용해 어떤 데이터가 다른 데이터에 의존할 때, 올바른 순서로 요청하고 관리할 수 있다.

const { data: user } = useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
  enabled: Boolean(userId), // userId가 있어야 실행
});

const { data: posts } = useQuery({
  queryKey: ['posts', user?.id],
  queryFn: () => fetchPosts(user?.id), // user가 있어야 실행
  enabled: Boolean(user), // user 데이터가 존재할 때만 실행
});

결과 예상

  1. userId가 있을 때 user 쿼리가 실행되어 fetchUser(userId)를 호출하고, user 데이터를 가져온다.
  2. user 데이터가 존재하면 posts 쿼리가 실행되어 fetchPosts(user.id)를 호출하고, posts 데이터를 가져온다.
  3. queryKey에 user?.id를 포함했기 때문에, user 데이터가 변경되면 posts 쿼리가 자동 갱신된다. userId가 변경된다면 user 쿼리가 자동 갱신된다.
  4. 따라서 userId가 없으면 user 쿼리가 실행되지 않고, user 쿼리가 실행되지 않으면 posts 쿼리도 실행되지 않는다.

2. 여러개의 API 요청 병합 : useQueries

useQueries

여러개의 useQuery를 한번에 실행시켜주는 훅이다. 각 요청을 병렬로 실행해서 성능 최적화가 가능하다.

기본 사용법

useQueries는 배열로 쿼리들을 받고 배열로 결과를 반환한다.

results는 각 useQuery의 반환값을 포함한 배열이라서 아래처럼 접근할 수 있다.

results[0].data → user 데이터
results[1].data → posts 데이터

const results = useQueries({
  queries: [
    {
      queryKey: ['user', userId],
      queryFn: () => fetchUser(userId)
    },
    {
      queryKey: ['posts', userId],
      queryFn: () => fetchPosts(userId)
    },
  ],
});

동적 개수의 useQuery 실행하기

useQueries는 배열을 받기 때문에, 동적인 개수의 쿼리도 실행할 수 있다.

const userIds = [1, 2, 3]; // 여러 개의 userId

const userQueries = useQueries({
  queries: userIds.map((id) => ({
    queryKey: ['user', id],
    queryFn: () => fetchUser(id),
    enabled: !!id,
  })),
});

응답 상태 다루기

some 메서드로 하나라도 로딩중/에러 라면 isLoading/isError를 true로 설정한다.

const isLoading = userQueries.some(query => query.isLoading);
const isError = userQueries.some(query => query.isError);
const users = userQueries.map(query => query.data).filter(Boolean);

3. useQueries결과 하나의 객체로 변환 : combine

useQueries의 combine 옵션으로 여러개의 쿼리 결과를 하나의 객체로 합칠 수 있다.

여러개의 쿼리 데이터를 원하는 형식으로 변환하고, isPending, isError 등의 상태도 원하는 대로 계산할 수 있다.

const ids = [1, 2, 3];

const combinedQueries = useQueries({
  queries: ids.map(id => ({
    queryKey: ['post', id],
    queryFn: () => fetchPost(id),
  })),
  combine: (results) => {
    return {
      data: results.map(result => result.data),  // 각 쿼리의 데이터를 배열로 정리
      pending: results.some(result => result.isPending), // 하나라도 로딩 중이면 true
      // 모든 데이터를 성공적으로 받아오면 true
      allSuccess: results.every(result => result.status === 'success') 
    };
  },
});

0개의 댓글

관련 채용 정보