useScheduledRefetch

React

๐Ÿ“Œ ๊ธฐ๋Šฅ ์š”์•ฝ

  • ํŠน์ • ๋ถ„(00, 15, 30, 45๋ถ„)๋งˆ๋‹ค ์ž๋™์œผ๋กœ refetch๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ›…
  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ refetch ํ•จ์ˆ˜๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ›์•„ ํ•œ ๋ฒˆ์— ์‹คํ–‰ ๊ฐ€๋Šฅ
  • ์ž๋™์œผ๋กœ ๋‹ค์Œ ์‹คํ–‰ ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ์ฃผ๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœ

๐Ÿ›  ๊ตฌํ˜„ ๋ฐฉ์‹

  1. ๋‹ค์Œ ์‹คํ–‰ ์‹œ๊ฐ ๊ณ„์‚ฐ
    • ํ˜„์žฌ ๋ถ„๊ณผ ์ดˆ๋ฅผ ๊ฐ€์ ธ์™€ minutes ๋ฐฐ์—ด์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋‹ค์Œ ๋ถ„์„ ์ฐพ์Œ
    • ํ˜„์žฌ๋ณด๋‹ค ๋ฏธ๋ž˜์˜ ๋ถ„์ด ์—†์œผ๋ฉด, ๋‹ค์Œ ์‹œ๊ฐ„(hour)์˜ ์ฒซ ๋ฒˆ์งธ ๋ถ„์œผ๋กœ ์„ค์ •
    • ๋‚จ์€ ์‹œ๊ฐ„(ms) ๊ณ„์‚ฐ ํ›„ setTimeout์œผ๋กœ ์˜ˆ์•ฝ
  2. ์ž๋™ ์‹คํ–‰
    • ์˜ˆ์•ฝ๋œ ์‹œ๊ฐ„์ด ๋˜๋ฉด ๋ชจ๋“  refetch ํ•จ์ˆ˜ ์‹คํ–‰
    • ์‹คํ–‰ ํ›„ ๋‹ค์‹œ scheduleNextRefetch() ํ˜ธ์ถœํ•˜์—ฌ ๋‹ค์Œ ์˜ˆ์•ฝ์„ ์„ค์ •
  3. ํšจ์œจ์ ์ธ ํƒ€์ด๋จธ ๊ด€๋ฆฌ
    • ๊ธฐ์กด ํƒ€์ด๋จธ๊ฐ€ ์žˆ์œผ๋ฉด clearTimeout์œผ๋กœ ์ œ๊ฑฐ ํ›„ ์ƒˆ๋กœ ์„ค์ •
    • useEffect์—์„œ minutes๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ํƒ€์ด๋จธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ์žฌ๊ณ„์‚ฐ

๐Ÿ’ก ํ›…

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import { useCallback, useEffect, useRef } from "react"; interface UseScheduledRefetchProps { refetch: (() => void)[]; // refetch ํ•จ์ˆ˜๋“ค์˜ ๋ฐฐ์—ด minutes: number[]; } const useScheduledRefetch = ({ refetch, minutes, }: UseScheduledRefetchProps) => { const timeoutRef = useRef<NodeJS.Timeout | null>(null); // ๋‹ค์Œ ๋ฆฌํŒจ์น˜ ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜ const scheduleNextRefetch = useCallback(() => { if (minutes.length === 0) return; // minutes๊ฐ€ ๋น„์–ด์žˆ์œผ๋ฉด ๋ฆฌํ„ด const now = new Date(); const currentMinute = now.getMinutes(); const currentSecond = now.getSeconds(); // ํ˜„์žฌ๋ณด๋‹ค ๋ฏธ๋ž˜์ธ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ„ ์ฐพ๊ธฐ let nextMinute = minutes.find((m) => m > currentMinute); // ํ˜„์žฌ ์‹œ๊ฐ„ ์ดํ›„์— ์‹คํ–‰ํ•  ๋ถ„์ด ์—†์œผ๋ฉด ๋‹ค์Œ ์‹œ๊ฐ„์˜ ์ฒซ ๋ฒˆ์งธ ๋ถ„์œผ๋กœ ์„ค์ • if (!nextMinute) { nextMinute = minutes[0]; } // ๋‹ค์Œ ์‹คํ–‰๊นŒ์ง€ ๋‚จ์€ ์‹œ๊ฐ„(ms) ๊ณ„์‚ฐ let msUntilNext; if (nextMinute > currentMinute) { // ๊ฐ™์€ ์‹œ๊ฐ„ ๋‚ด ๋‹ค์Œ ๋ถ„ msUntilNext = ((nextMinute - currentMinute) * 60 - currentSecond) * 1000; } else { // ๋‹ค์Œ ์‹œ๊ฐ„์˜ ์ฒซ ๋ถ„ (์˜ˆ: ํ˜„์žฌ 45๋ถ„์ด๊ณ  ๋‹ค์Œ์€ 00๋ถ„) msUntilNext = ((60 - currentMinute + nextMinute) * 60 - currentSecond) * 1000; } // ์ด์ „ ํƒ€์ด๋จธ ์ •๋ฆฌ if (timeoutRef.current) clearTimeout(timeoutRef.current); timeoutRef.current = setTimeout(() => { // ๋ชจ๋“  refetch ํ•จ์ˆ˜ ์‹คํ–‰ refetch.forEach((fn) => fn()); scheduleNextRefetch(); // ๋‹ค์Œ ๋ฆฌํŒจ์น˜ ์˜ˆ์•ฝ }, msUntilNext); }, [minutes, refetch]); useEffect(() => { // minutes๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ฆ‰์‹œ ๋‹ค์Œ ์Šค์ผ€์ค„ ์žฌ๊ณ„์‚ฐ scheduleNextRefetch(); // ์ •๋ฆฌ ํ•จ์ˆ˜ return () => { if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, [scheduleNextRefetch, minutes]); return null; }; export default useScheduledRefetch

๐Ÿ’ก ํ™œ์šฉ ์˜ˆ์‹œ

1 2 3 4 5 6 7 const { data, refetch } = useQuery("fetchData", fetchDataFn); const { data: chartData, refetch: chartRefetch } = useQuery("fetchChart", fetchChartFn); useScheduledRefetch({ refetch: [refetch, chartRefetch], minutes: [0, 15, 30, 45], });

โœ… ํŠน์ง• ๋ฐ ์žฅ์ 

  • ์žฌ์‚ฌ์šฉ์„ฑ ์ฆ๊ฐ€: refetch ํ•จ์ˆ˜๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ›์•„ ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • ์ฝ”๋“œ ์ค‘๋ณต ๊ฐ์†Œ: ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ํ›…์„ ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด ํ•œ ๋ฒˆ๋งŒ ์„ ์–ธ
  • ์ž๋™ ์Šค์ผ€์ค„๋ง: ๋งค ์‹œ๊ฐ 00, 15, 30, 45๋ถ„์— ๋งž์ถฐ ํ˜ธ์ถœ๋จ
  • ํƒ€์ด๋จธ ๊ด€๋ฆฌ ์ตœ์ ํ™”: ๊ธฐ์กด ํƒ€์ด๋จธ๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์ƒˆ๋กœ์šด ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€

โš ๏ธ์ฃผ์˜

  • ํ•ด๋‹น ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ ์†์„ฑ์ค‘ refetchInterval ์€ ํ•ด์ œ ์š”๋ง