ํฐ์คํ ๋ฆฌ ๋ทฐ
Tanstack Query
๐Tanstack : ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์๋ฒ ์ํ ๊ด๋ฆฌ๋ฅผ ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ํ ์คํ์ useQuery ๊ฐ์ ํ
์ ์ฌ์ฉํด์ผ ํ๋ค.
๋๋ฌธ์ Provider ์ปดํฌ๋ํธ๋ ๋ฐ๋์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ด๋ค. - QueryClientProvider๋ React Context๋ฅผ ์ฌ์ฉํด์ ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌ
React์ Context API๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์๋ง ์ฌ์ฉ - ์ ์ญ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ต์๋จ(root layout)์ ์ ์ฉ
๐คํด๋ผ์ด์ธํธ ์ฌ์ด๋์์๋ง ์ ์ฉ์ํค๋๋ฐ ์ ์ ์ญ์ ์ ์ฉํด์ผ ํ ๊น?
- ํ์ด์ง ์ด๋ ์ ํด๋ผ์ด์ธํธ ์ํ๊ฐ ์ด๊ธฐํ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ญ์์ ์บ์ฑ
- ๋ชจ๋ ํ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์ ๋์ผํ QueryClient ์ธ์คํด์ค๋ฅผ ์ฌ์ฉ
์๋ฒ ์ปดํฌ๋ํธ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ
๐์๋ฒ ์ปดํฌ๋ํธ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์ ๊ด๊ณ
- ์๋ฒ ์ปดํฌ๋ํธ ๋ด๋ถ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๊ฐ ํฌํจ๋ ์ ์๋๊ฐ?
- ๊ฐ๋ฅํ๋ค. ์๋ฒ ์ฌ์ด๋์์ ๋๋๋ง ๋์ด์ ์ ์ ์ผ๋ก ๋ง๋ค์ด์ง ํ์ด์ง์์
๋ถ๋ถ์ ์ฐจ์งํ๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ ๋์ ์ผ๋ก ์๋ํ๋ค. (์ ์ฒด ํ์ด์ง๋ ๋์ ์ธ ํ์ด์ง๊ฐ ๋จ.)
- ๊ฐ๋ฅํ๋ค. ์๋ฒ ์ฌ์ด๋์์ ๋๋๋ง ๋์ด์ ์ ์ ์ผ๋ก ๋ง๋ค์ด์ง ํ์ด์ง์์
- ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ ๋ด๋ถ์ ์๋ฒ ์ปดํฌ๋ํธ๊ฐ ํฌํจ๋ ์ ์๋๊ฐ?
- ๋ถ๊ฐ๋ฅํ๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ ์๋ฒ์์๋ง ๋๋๋ง๋๊ธฐ ๋๋ฌธ์ JS ๋ฒ๋ค ํ์ผ์ ํฌํจ๋์ง ์๋๋ค.
๋ฐ๋ผ์ ๋ธ๋ผ์ฐ์ ์์๋ง ์คํํ๋ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ์์๋ ์๋ฒ ์ ์ฉ ์ฝ๋(์: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ, ํ์ผ ์์คํ ์ ๊ทผ ๋ฑ)๋ฅผ ์ง์ ์คํํ ์ ์๋ค.
- ๋ถ๊ฐ๋ฅํ๋ค. ์๋ฒ ์ปดํฌ๋ํธ๋ ์๋ฒ์์๋ง ๋๋๋ง๋๊ธฐ ๋๋ฌธ์ 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)
'Language > Next' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [/\/] Tanstack Query + Zustand ์ ์ญ ์ํ ๊ด๋ฆฌํ๊ธฐ (0) | 2025.03.21 |
|---|---|
| [/\/] Next.js์์ ๋งํ๋ '์๋ฒ'๋? (0) | 2025.03.19 |
| [/\/] Error Handling (0) | 2025.03.19 |
| [/\/] Loading UI - Suspense ์ Streaming SSR (0) | 2025.03.11 |
| [/\/] SSG, ISR, SSR, CSR (0) | 2025.03.10 |