Skip to content

๐Ÿ”– useInfiniteQuery๋ฅผ ์‚ฌ์šฉํ•œ ๊ทธ๋ž˜ํ”„ ๋ฌดํ•œ์Šคํฌ๋กค ๊ตฌํ˜„

baegyeong edited this page Dec 2, 2024 · 3 revisions
๋ถ„์•ผ ์ž‘์„ฑ์ž ์ž‘์„ฑ์ผ
FE ์กฐ๋ฐฐ๊ฒฝ 24๋…„ 12์›” 03์ผ

๋ฌธ์ œ ์ƒํ™ฉ

๋ฌดํ•œ์Šคํฌ๋กค๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ๊ฐฑ์‹ ๋œ๋‹ค.

๊ทธ๋Ÿผ ์ด์ „ ๊ฐ’๋“ค์€ ์šฐ์งธ..

image


์ฃผ์ถค์ฃผ์ถค ์„œ๋น„์Šค์—์„œ๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ์กฐํšŒํ•˜๋Š”๋ฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— 100๊ฐœ์”ฉ ์ž˜๋ผ์„œ ์‘๋‹ต์„ ๋ฐ›๋Š”๋‹ค.

๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์™ผ์ชฝ์œผ๋กœ ์Šคํฌ๋กคํ•˜์—ฌ ์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค ํ•œ๋‹ค๋ฉด, ํ˜ธ์ถœํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐ€์žฅ ์ตœ์‹  ์‹œ๊ฐ„(lastStartTime)์„ ํ•จ๊ป˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์•ผํ•œ๋‹ค.

ํ˜ธ์ถœํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐ€์žฅ ์ตœ์‹  ์‹œ๊ฐ„์ด๋ž€, ํ˜„์žฌ ๋ณด์—ฌ์ง€๋Š” ๊ทธ๋ž˜ํ”„์˜ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์‹œ๊ฐ„๊ณผ ๊ฐ™๋‹ค.


๋”ฐ๋ผ์„œ ๊ทธ๋ž˜ํ”„๋ฅผ ์Šคํฌ๋กคํ•˜๋‹ค๊ฐ€ ๊ทธ๋ž˜ํ”„ ๊ฐ€์‹œ๋ฒ”์œ„์˜ ์‹œ์ž‘์ ์ด ํŠน์ • ์œ„์น˜๋ณด๋‹ค ์ž‘์•„์ง€๋ฉด, ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•œ๋‹ค.

์ด๋•Œ, lastStartTime์„ useState๋กœ ์ €์žฅํ•˜์—ฌ ์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

const fetchGraphData = (logicalRange) => {
  // ํŠน์ • ์œ„์น˜์— ๋‹ฟ์œผ๋ฉด
  if (logicalRange && logicalRange.from < -50 && hasNextPage) {
     // ํ˜„์žฌ ๋ฐ์ดํ„ฐ์˜ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์‹œ๊ฐ„์„ lastStartTime ์ƒํƒœ์— ์ €์žฅ
    setLastStartTime(data?.pages[0].priceDtoList[0].startTime); 

    // ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ํŠธ๋ฆฌ๊ฑฐ
    fetchNextPage();
  }
};

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š”, ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค data๊ฐ€ ๊ฐฑ์‹ ๋˜์–ด ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋งŒ ๊ทธ๋ž˜ํ”„์— ๋ณด์˜€๋‹ค. ์ฆ‰ ์Šคํฌ๋กคํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋ฉด, ๊ฐ’์ด ๋ˆ„์ ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•ญ์ƒ ์Šคํฌ๋กค๋˜์–ด ์–ป์€ ๊ฐ’์œผ๋กœ ๊ฐฑ์‹ ๋œ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ํ•ญ์ƒ ๋”ฐ๋กœ ๊ฐ’์„ ๋ˆ„์ ํ•ด์„œ ์ €์žฅํ•ด์ค˜์•ผํ• ๊นŒ ์‹ถ์—ˆ๋‹ค.


ํ•˜์ง€๋งŒ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ์‘๋‹ต๊ฐ’์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด tanstack query๋กœ ๊ด€๋ฆฌํ•˜๊ณ , ๋ˆ„์ ์„ ์œ„ํ•ด useState๋กœ ๊ด€๋ฆฌํ•œ๋‹ค๋Š” ๊ฒŒ ๋ฒˆ๊ฑฐ๋กœ์šธ ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋ฏธ ๊ตฌํ˜„๋˜์–ด ์žˆ์ง„ ์•Š์€์ง€ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๋‹ˆ, useInfiniteQuery๋Š” ์‘๋‹ต๊ฐ’์— ์ด๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ˆ„์ ํ•˜์—ฌ ์ €์žฅํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.


useInfiniteQuery์˜ ์˜ต์…˜ ์ดํ•ดํ•˜๊ธฐ

useInfiniteQuery์˜ ๋ฐ˜ํ™˜๊ฐ’ ์ค‘ data๋Š”, pages์™€ pageParams๋ฅผ ํฌํ•จํ•œ๋‹ค.

  • pages: ๋ฌดํ•œ์Šคํฌ๋กคํ•˜์—ฌ ์–ป์–ด์ง€๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋ˆ„์ ๋˜์–ด ์ €์žฅ
  • pageParam: ์š”์ฒญ์— ํ•„์š”ํ•œ ํŽ˜์ด์ง€ ํŒŒ๋ผ๋ฏธํ„ฐ

์šฐ๋ฆฌ ํŒ€ api์—๋Š” pageParam์„ ๋ณ„๋„๋กœ ๋„˜๊ธฐ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ณ  ์žˆ์—ˆ๋˜ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‘๋‹ต๊ฐ’์„ ํ™•์ธํ•ด๋ด๋„ ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ ๊ฐฑ์‹ ๋˜์–ด ์žˆ์—ˆ๋‹ค. ์ด๋Š”, ์š”์ฒญ์˜ ์˜ต์…˜ ์ž์ฒด๊ฐ€ ์ž˜๋ชป ์„ค์ •๋œ ๊ฒƒ์ด์—ˆ๋‹ค.

export const useGetStocksPriceSeries = ({
  stockId,
  lastStartTime,
  timeunit,
}: StockTimeSeriesRequest) => {
  return useInfiniteQuery({
    queryKey: ['stocksTimeSeries', stockId, lastStartTime, timeunit],
    queryFn: () => getStocksPriceSeries({ stockId, lastStartTime, timeunit }),
    getNextPageParam: (data) => (data.hasMore ? true : null),
    initialPageParam: true,
  });
};

getNextPageParam์™€ initialPageParam์„ ์ถ”๊ฐ€๋กœ ์˜ต์…˜์œผ๋กœ ์„ค์ •ํ–ˆ๋Š”๋ฐ, ์ด ์˜๋ฏธ๋ฅผ ์ œ๋Œ€๋กœ ํŒŒ์•…ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

getNextPageParam์€, ๋‹ค์Œ ์š”์ฒญ์— ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ฆ‰ ๋ฌดํ•œ์Šคํฌ๋กค ์š”์ฒญ ์‹œ๋งˆ๋‹ค lastStartTime์˜ ์ƒํƒœ๋ฅผ ์ƒˆ๋กœ ์ €์žฅํ–ˆ๋˜ ๋กœ์ง์„ getNextPageParam์—์„œ ์ง„ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

initalPageParam์€ ๋ง๊ทธ๋ž˜๋„ ์ดˆ๊ธฐ page ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์ด๋ฏ€๋กœ, lastStartTime์„ ๋„˜๊ฒจ์•ผํ•œ๋‹ค.


์•„๋ž˜๋Š” ์ˆ˜์ •๋œ ์ฝ”๋“œ์ด๋‹ค.

export const useGetStocksPriceSeries = ({
  stockId,
  lastStartTime,
  timeunit,
}: StockTimeSeriesRequest) => {
  return useInfiniteQuery({
    queryKey: ['stocksTimeSeries', stockId, lastStartTime, timeunit],
    // ์š”์ฒญ์‹œ๋งˆ๋‹ค ๋„˜๊ธธ pageParam์„ ๋„ฃ์–ด์ฃผ๊ธฐ
    queryFn: ({ pageParam }) => getStocksPriceSeries({ 
      stockId, 
      lastStartTime: pageParam?.lastStartTime ?? lastStartTime,
      timeunit 
    }),
    // ๋‹ค์Œ ์š”์ฒญ์— ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š”, hasMore๊ฐ€ true์ผ ๋•Œ ์„ค์ •ํ•ด์ฃผ๊ธฐ. ์ด์ „์˜ setState ๊ณผ์ •์ด ํ•„์š” ์—†์–ด์ง„๋‹ค!
    getNextPageParam: (lastPage) => 
      lastPage.hasMore 
        ? { 
            lastStartTime: lastPage.priceDtoList[0].startTime 
          } 
        : undefined,
    initialPageParam: { lastStartTime },
  });
};

๊ทธ ๊ฒฐ๊ณผ, ๊ฐฑ์‹ ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ pages์— ์ฐจ๊ณก์ฐจ๊ณก ๋‹ด๊ธด๋‹ค!

image


์‚ฌ์‹ค์€ ์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์ด๋‹ˆ getNextPageParam ๋Œ€์‹ ์—๋Š” getPreviousPageParam, hasNextPage ๋Œ€์‹ ์— hasPreviousPage๋ฅผ ์“ฐ๋Š” ๊ฒŒ ์˜๋ฏธ์ƒ ์ ์ ˆํ•˜๋‹ค.

ํ•˜์ง€๋งŒ getPreviousPageParam๋ฅผ ์‚ฌ์šฉํ•˜๋ คํ•˜๋ฉด, ์ด ํ˜ธ์ถœ๊ณผ ์ผ์น˜ํ•˜๋Š” ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.๋ผ๊ณ  ์›์ธ ๋ชจ๋ฅผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

๋˜ํ•œ getPreviousPageParam์˜ ์ฝœ๋ฐฑ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ firstPage, allPages, firstPageParam, allPageParams๋กœ hasMore๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์–ด ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์€ ๋กœ์ง์„ ์งค ์ˆ˜ ์—†์—ˆ๋‹ค.

๋”ฐ๋ผ์„œ getNextPageParam์„ ์ด์šฉํ•ด ์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , select ์˜ต์…˜์— reverse()๋ฅผ ํ†ตํ•ด ์—ญ์ˆœ์œผ๋กœ ์ €์žฅํ•˜์—ฌ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๊ณ  ์žˆ๋‹ค.

select: (data) => ({
  pages: [...data.pages].reverse(),
  pageParams: [...data.pageParams].reverse(),
}),

๐Ÿœ ํŒ€ ๊ฐœ๋ฏธ

๐Ÿ›๏ธ ํŒ€ ๋ฌธํ™”

๊ฐœ๋ฐœ ์œ„ํ‚ค

FE

BE

Infra

๐Ÿ—ฃ๏ธ ๋ฐœํ‘œ

๐Ÿ“š ํšŒ์˜๋ก

๐Ÿ”ด ์ธํ„ฐ๋ฏธ์…˜
๐ŸŸ  1์ฃผ์ฐจ
๐ŸŸก 2์ฃผ์ฐจ
๐ŸŸข 3์ฃผ์ฐจ
๐Ÿ”ต 4์ฃผ์ฐจ
๐ŸŸฃ 5์ฃผ์ฐจ
๐ŸŸค 6์ฃผ์ฐจ

๐Ÿ’ญ ํšŒ๊ณ 

๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ ๋ฉ˜ํ† ๋ง

Clone this wiki locally