Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] React Qeury - Parallel Queries

Updated
3 min readView as Markdown
[ 살펴보기 ] React Qeury - Parallel Queries
C

A developer living in Busan, Korea

Parallel queries란 useQuery로 데이터를 fetch할 때 앞서 선언된 useQuery fetch를 기다리지 않고 선언된 useQuery의 수 만큼 동시에 request를 보내는 것을 의미한다

React Query에서는 별도의 조작 없이 useQuery를 여러개 쓰면 library에서 알아서 parallel request를 수행해준다

즉, 아래의 코드는 request가 동시에 처리된다

const { data: userData } = useQuery({
  queryKey: ["users"],
  queryFn: async () => {
    const res = await getUserList();
    return res;
  },
});
const { data: orderData } = useQuery({
  queryKey: ["orders"],
  queryFn: async () => {
    const res = await getOrderList();
    return res;
  },
});

개발자도구의 네트워크 탭을 보면 다음과 같이 요청이 동시에 보내졌음을 확인할 수 있다

Suspense와 Parallel request

하지만 Suspense를 통해 loading page logic을 처리하고 있다면 이야기가 달라진다. 다음 예제를 살펴보자

<Suspense fallback={<div>Loading...</div>}>
  <OrderSuspenseList />
</Suspense>
// OrderSuspenseList.tsx

const { data: orderList } = useSuspenseQuery({
  queryKey: ["order-sus-list"],
  queryFn: async () => {
    const res = await getOrderList();
    return res;
  },
});
const { data: userList } = useSuspenseQuery({
  queryKey: [`user-sus-list`],
  queryFn: async () => getUserList(),
});

위의 코드를 살펴보면 OrderSuspenseList component에서 user 데이터와 order 데이터를 useSuspenseQuery를 통해 request 요청 처리를 하고 있고 OrderSuspenseList component의 data fetch 과정이 모두 끝날 때까지 Suspense의 fallback 화면으로 대체한다

위의 예제에서는 제일 처음봤던 예제와는 달리 request처리가 parallel형식으로 되지 않는다. 즉, order data request 과정이 끝나고 user data request 과정이 시작된다. request 처리가 차례대로 진행되는 것이다.

네트워크 탭을 보면 위의 예제와는 달리 orders request가 우선 처리 되는 것을 확인할 수 있다

orders request가 끝나고 나서야 비로서 users request가 시작된다

그렇다면 suspense를 사용할 떄 parallel request를 어떻게 구현할 수 있을까?

Component의 분리

Suspense를 적용하면 보통 data를 fetch하는 부분과 data를 사용하는 부분을 가까운 곳에 두게된다. 그렇기에 다음과 같이 data fetch 부분과 data 사용부분을 나눌 수 있는 사안이라면 component를 각자 나누어 하나의 suspense로 묶으면 request은 다시 parallel 형식으로 진행된다

<Suspense fallback={<div>Loading...</div>}>
  <OrderSuspenseList />
  <UserSuspenseList />
</Suspense>

위의 예제에서 OrderSuspenseList는 order data를 fetch하는 useSuspenseQuery 하나만 가지고 있고 UserSuspenseList는 user data를 fetch하는 useSuspenseQuery를 하나만 가지고 있다

위와 같이 각각의 useSuepenseQuery와 UI 구현부를 각자의 component로 떼어내고 하나의 Suspense로 묶으면 request는 다시 parallel 형식으로 동시 진행이 된다

useSuspenseQueries

하지만 위 처럼 component를 떼어놓을 수 없는 상황이라면 useSuspenseQueries를 통해 request는 parallel 형식으로 동시 진행할 수 있다

<Suspense fallback={<div>Loading...</div>}>
  <OrderSuspenseList />
</Suspense>
// OrderSuspenseList.tsx
const queryList = useSuspenseQueries({
  queries: [getUserList, getOrderList].map((queryFunc, index) => {
    return {
      queryKey: [`${queryFunc.name}`],
      queryFn: () => queryFunc(),
    };
  }),
});

위의 예제와 같이 useSuspenseQueries는 query에 사용되는 queryKey와 queryFn의 배열을 queries 옵션에 전달받는다.

그리고 usesuspenseQueries가 반환하는 값에는 queries에 전달한 결과 값이 차례대로 배열로 반환된다 ( 위의 예제에서는 queryList 변수의 첫 번째 값은 getUserList가 queryFn으로 전달된 useSuspenseQuery return 값이, 그리고 두 번째 값은 getOrderList가 queryFn으로 전달된 susSuspenseQuery return 값이 담겨져 있다 )

Network 탭을 확인해 보면 request가 parallel 방식으로 동시에 진행이 되는 것을 확인할 수 있다

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts