Next.js
React Query
React Query๋ฅผ ํตํด, useEffect์ data-fetch๋ฅผ ํ๋ฒ์ ํ ์ ์๋ค.
useQuery({ queryKey: ["til", { category: "trending" }] });
//category์ธ์ page, sort๊ฐ์๊ฒ๋ ๊ฐ์ด ๋ฃ๋๋ค๊ณ ํ๋ค.
โ๏ธ react query๋ ์๋ฒ์ ๋๊ธฐํ ํ๊ธฐ ๋๋ฌธ์, ๊ฐ๋์ local์ชฝ data๋ฅผ ๋ ๋ฆฌ๊ณ ์๋ก ๋ฐ์์ค๋ ์์ ์ ํ๋ค๊ณ ํ๋ค. (invalidate)
๐๐ป key๋ฅผ ๊ตฌ๋ถํด, ์ ์ฒด ๋ฐ๊ตฌ๋๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ด ์๋๋ผ til๋ง ์ด๊ธฐํ ํ๋ค.
โqueryKey: ๋ถ์ํ๊ณ ์ ๋ฆฌํ๋ค.
โqueryFn: fetch์ ๊ฐ์ ํจ์๋ฅผ ์ ์ํ๊ณ , fetch๋๋ฉด queryKey์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ก ์ ๋ฆฌ๋์ด ๋ค์ด๊ฐ๋ค.
โจ Next.js์์ React Query๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ํด๋ผ์ด์ธํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค.
useMutation
์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํด ์ฌ์ฉ๋๋๋ฐ, ๋ฐ์ดํฐ์ ์์ฑ(Create), ์์ (Update), ์ญ์ (Delete)ํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
โ ๋ฐ์ดํฐ ๋ณํ๊ฐ ์ด๋ฃจ์ด์ง๋ ๋ค์ ์๋ฒ๋ก๋ถํฐ GET์์ฒญ์ ํตํด ์ต์ ๋ฐ์ดํฐ๋ฅผ ์ ์งํ ์ ์๋ค.
โ useQuery์ ์ฌ์ฉ๋ฒ์ด ๊ฑฐ์ ๋์ผํ๋ค.
import { useMutation } from "react-query";
const { data, isLoading, mutate } = useMutation(fetch, options);
๐ค useQuery๋ก ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๊ฐ ๋ณ๋๋์ด์ ๋ฆฌ๋ ๋๋ง๋์ด์ผ ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
useState ๋๋ useRef์ ํจ๊ป ์ฌ์ฉํ๊ธฐ: useQuery ํ ์์ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ useState ๋๋ useRef๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ์ ์ํ๋ก ๊ด๋ฆฌํฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ ๋ฐ์ดํธ๋๋ฉด ์ํ๊ฐ ์ ๋ฐ์ดํธ๋๊ณ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค.
import { useQuery } from '@apollo/client';
import { useState } from 'react';
function MyComponent() {
const { loading, data } = useQuery(MY_QUERY);
const [myData, setMyData] = useState(null);
useEffect(() => {
if (!loading && data) {
setMyData(data);
}
}, [loading, data]);
if (loading) return <p>Loading...</p>;
if (!myData) return null;
return (
<div>
{/* Display myData */}
</div>
);
}
useEffect๋ฅผ ์ฌ์ฉํ์ฌ ์๋์ผ๋ก ์ ๋ฐ์ดํธ ๊ฐ์งํ๊ธฐ: useQuery๋ก ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค useEffect๋ฅผ ์ฌ์ฉํ์ฌ ํ์ํ ์์ ์ ์ํํฉ๋๋ค.
import { useQuery } from '@apollo/client';
import { useState, useEffect } from 'react';
function MyComponent() {
const { loading, data } = useQuery(MY_QUERY);
const [myData, setMyData] = useState(null);
useEffect(() => {
if (!loading && data) {
setMyData(data);
}
}, [loading, data]);
useEffect(() => {
// ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ํ์ํ ์์
์ํ
}, [myData]);
if (loading) return <p>Loading...</p>;
if (!myData) return null;
return (
<div>
{/* Display myData */}
</div>
);
}
Apollo Client์ refetch ๊ธฐ๋ฅ ์ฌ์ฉํ๊ธฐ: useQuery ํ ์์ refetch ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ ธ์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ฟผ๋ฆฌํ์ฌ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ด๋ฏ๋ก ์ฃผ๋ก ์ฌ์ฉ์ ์ก์ ์ ๋ฐ์ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
import { useQuery } from '@apollo/client';
function MyComponent() {
const { loading, data, refetch } = useQuery(MY_QUERY);
if (loading) return <p>Loading...</p>;
return (
<div>
{/* Display data */}
<button onClick={() => refetch()}>Refresh Data</button>
</div>
);
}
context API , Reudx, useQuery ๋น๊ต
โ Context API: Context API๋ React์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ผ๋ก, ์ปดํฌ๋ํธ ํธ๋ฆฌ ์ ์ฒด์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค. ์์ ๊ท๋ชจ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ ๊ฐ๋จํ ์ํ ๊ด๋ฆฌ์ ์ ์ฉํฉ๋๋ค. ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐ๋ก ์ค์นํ ํ์๊ฐ ์์ด์ ํ๋ก์ ํธ์ ์์กด์ฑ์ ์ค์ผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ํ์ ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ๋ฉด ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์์ง ์ ์์ต๋๋ค.
โ Redux: Redux๋ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ํ๋์ ๋๋ค. ์ํ์ ์ค์ ์ง์คํ๋ฅผ ํตํด ์ํ ๋ณํ๋ฅผ ์์ธก ๊ฐ๋ฅํ๊ฒ ๋ง๋ค์ด์ค๋๋ค. ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ํ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ํ์ง๋ง Redux๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๋ณ๋์ ํ์ต์ด ํ์ํ๊ณ , ์ถ๊ฐ์ ์ธ ์ฝ๋๋์ด ๋์ด๋ ์ ์์ต๋๋ค.
โ useQuery (Apollo Client): useQuery๋ Apollo Client์์ ์ ๊ณตํ๋ React ํ ์ผ๋ก, GraphQL ์ฟผ๋ฆฌ๋ฅผ ์ํํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ๋ง์ฝ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฃผ์ ๋ฐ์ดํฐ๊ฐ GraphQL์ ํตํด ๊ด๋ฆฌ๋๋ค๋ฉด, Apollo Client๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ ์ ํ ์ ์์ต๋๋ค. ํ์ง๋ง useQuery๋ ์ฃผ๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ์ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ์ํ์ ๋ณ๊ฒฝ ๋ฐ ์ ๋ฐ์ดํธ์๋ ์กฐ๊ธ ๋ ์์ ์ด ํ์ํ ์ ์์ต๋๋ค.