ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

Language/Next

[/\/] Next์˜ Tanstack Query

์ฑ„._. 2025. 3. 19. 00:29

Tanstack Query

 

๐Ÿ“Tanstack : ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • ํƒ ์Šคํƒ์€ useQuery ๊ฐ™์€ ํ›…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
    ๋•Œ๋ฌธ์— Provider ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐ˜๋“œ์‹œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.
  • QueryClientProvider๋Š” React Context๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌ
    React์˜ Context API๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉ
  • ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ƒ๋‹จ(root layout)์— ์ ์šฉ

๐Ÿค”ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ๋งŒ ์ ์šฉ์‹œํ‚ค๋Š”๋ฐ ์™œ ์ „์—ญ์— ์ ์šฉํ•ด์•ผ ํ• ๊นŒ?

  • ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ€ ์ดˆ๊ธฐํ™”๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ „์—ญ์—์„œ ์บ์‹ฑ
  • ๋ชจ๋“  ํ•˜์œ„ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋™์ผํ•œ QueryClient ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉ

 

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ

 

๐Ÿ“์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ๊ด€๊ณ„

  • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š”๊ฐ€?
    • ๊ฐ€๋Šฅํ•˜๋‹ค. ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ ๋žœ๋”๋ง ๋˜์–ด์„œ ์ •์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„ ํŽ˜์ด์ง€์—์„œ
      ๋ถ€๋ถ„์„ ์ฐจ์ง€ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋™์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค. (์ „์ฒด ํŽ˜์ด์ง€๋Š” ๋™์ ์ธ ํŽ˜์ด์ง€๊ฐ€ ๋จ.)
  • ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š”๊ฐ€?
    • ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„์—์„œ๋งŒ ๋žœ๋”๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์— JS ๋ฒˆ๋“ค ํŒŒ์ผ์— ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค.
      ๋”ฐ๋ผ์„œ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋งŒ ์‹คํ–‰ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์„œ๋ฒ„ ์ „์šฉ ์ฝ”๋“œ(์˜ˆ: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ, ํŒŒ์ผ ์‹œ์Šคํ…œ ์ ‘๊ทผ ๋“ฑ)๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.

 

Next.js์—์„œ Tanstack ์ ์šฉ ๋ฐฉ๋ฒ•


ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ ํฌํ•จ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ๊ฐ„์ ‘์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ”๋กœ {children}์„ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

 

tanstack์— ์ ์šฉํ•ด์„œ ์˜ˆ์‹œ๋ฅผ ๋“ค์ž๋ฉด,

ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์ธ Provider.tsx ํŒŒ์ผ์— QueryClient๋ฅผ ์„ ์–ธํ•˜๊ณ  provider ์‚ฌ์ด์— {children}์„ ์œ„์น˜์‹œํ‚จ๋‹ค.

// provider.tsx

"use client";

import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import React from "react";

const Provider = ({ children }: { children: React.ReactNode }) => {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
};

export default Provider;

๊ทธ๋ฆฌ๊ณ  ์ „์—ญ์—์„œ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ƒ๋‹จ root layout์— provider๋ฅผ ์ ์šฉ์‹œํ‚จ๋‹ค.

//src > app > layout.tsx
...
return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <nav className="flex justify-evenly bg-emerald-800 py-[10px]">
          <Link className="navFont" href={"/"}>
            Home
          </Link>
          <Link className="navFont" href={"/champions"}>
            Champions
          </Link>
          <Link className="navFont" href={"/rotation"}>
            Rotation
          </Link>
          <Link className="navFont" href={"/items"}>
            Items
          </Link>
        </nav>
        <Provider>{children}</Provider> โญ๏ธ
      </body>
    </html>
  );

 

 

์ด์ œ, ์ „์—ญ์—์„œ tanstack์„ ํ†ตํ•ด ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ useQuery ๊ฐ™์€ ํ›…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿค”๋งŒ์•ฝ ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด useQuery๋ฅผ ๋บ€๋‹ค๋ฉด?

  • ์ปค์Šคํ…€ ํ›…์€ “use client”๋ฅผ ๋ช…์‹œ X
  • ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ use client ๋ช…์‹œํ•˜๋ฉด ์ž๋™์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋จ
// hooks > queries.tsx

import { useQuery } from "@tanstack/react-query";
import { CHAMPION_IMG_URL } from "../constants/riotDataURL";
import { getChampionRotation } from "@/utils/riotApi";
import { QUERY_KEY } from "../constants/queryKey";

export const getImgUrl = () => {
  return useQuery({
    queryKey: [QUERY_KEY.IMG_URL],
    queryFn: CHAMPION_IMG_URL,
  });
};

export const getRotation = () => {
  return useQuery({
    queryKey: [QUERY_KEY.ROTATION],
    queryFn: getChampionRotation,
  });
};

 

// rotation > page.tsx

"use client";

import { getImgUrl, getRotation } from "../hooks/quries";
import Card from "@/_components/Card";

export default function Rotationpage() {
  const { data: imgUrl, isPending, isError, error } = getImgUrl();
  const { data: rotation = [] } = getRotation();

  if (isPending) {
    return <div>๋กœ๋”ฉ ์ค‘์ž…๋‹ˆ๋‹ค..</div>;
  }

  if (isError) {
    return (
      <>
        <div>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค!</div>
        <p>์—๋Ÿฌ:{error.message}</p>
      </>
    );
  }

  return (
  ...

 

๐Ÿค”๊ทธ๋ ‡๋‹ค๋ฉด ์„œ๋ฒ„์—์„œ๋Š” ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

  • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์ง์ ‘ ๋ฐ์ดํ„ฐ fetch (tanstack ์‚ฌ์šฉ X)

 

๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2026/03   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
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
๊ธ€ ๋ณด๊ด€ํ•จ