07. ๐ก ์๋ฒ ์ํ ๊ด๋ฆฌ์ ์บ์ฑ ์ ๋ต ๋ง์คํฐ
๐ ๊ฐ์
React Query(TanStack Query)๋ฅผ ํตํด ์๋ฒ ๋ฐ์ดํฐ๋ฅผ '์ํ'๊ฐ ์๋ '์บ์'๋ก ๋ค๋ฃจ๋ ํจ๋ฌ๋ค์ ๋ณํ๋ฅผ ์ดํดํฉ๋๋ค.
๐ ์ด ๋ฉด์ ํญ๋ชฉ์ ๋ชฉํ
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 24๋ถ (ํต์ฌ ์์ฝ: 12๋ถ)
๐บ๏ธ ์ด ์ฑํฐ์ ํ๋ฆ
[๊ฐ๋
์ฌ์ ] โ [์ง๋ฌธ 1: ํด๋ผ์ด์ธํธ ์ํ vs ์๋ฒ ์ํ] โ [์ง๋ฌธ 2: ์บ์ฑ ๋ฐ ์ ์ ๋ ๊ด๋ฆฌ] โ [์ค์ ๋ณํ ์ง๋ฌธ]
๐ฏ ์ด ์ฑํฐ๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- ์ ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ์ ์ญ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Zustand ๋ฑ)์ ์ ์ฅํ๋ฉด ์ ๋๋์ง ์ค๋ช ํฉ๋๋ค.
Stale-While-Revalidate์ ๋ต์ด ์ฌ์ฉ์ ๊ฒฝํ์ ์ด๋ป๊ฒ ๊ฐ์ ํ๋์ง ์ดํดํฉ๋๋ค.- ๋ฌดํ ์คํฌ๋กค, ๋๊ด์ ์ ๋ฐ์ดํธ ๋ฑ ๋ณต์กํ ๋น๋๊ธฐ ํจํด์ ๊ตฌํ ์๋ฆฌ๋ฅผ ๋ง์คํฐํฉ๋๋ค.
๐ ํต์ฌ ๊ฐ๋ ์ฌ์ (Concept Glossary)
1. ์๋ฒ ์ํ (Server State)
๋ด๊ฐ ์์ ํ์ง ์์, ์๊ฒฉ์ง์ DB์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ ๋๋ค. ์ธ์ ๋ ๋ค๋ฅธ ์ฌ์ฉ์์ ์ํด ๋ฐ๋ ์ ์์ผ๋ฉฐ(Out-of-sync), ๊ฐ์ ธ์ค๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ๋น๋๊ธฐ์ ํน์ฑ์ ๊ฐ์ง๋๋ค.
2. SWR (Stale-While-Revalidate)
"์ํ(Stale) ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๋ณด์ฌ์ฃผ๋, ๊ทธ๋์ ์๋ฒ์์ ์ ์ ํ(Fresh) ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ ธ์(Revalidate) ์กฐ์ฉํ ๊ต์ฒดํ๋ค"๋ ์บ์ฑ ์ ๋ต์ ๋๋ค. ์ฌ์ฉ์์๊ฒ '๋๊ธฐ ์๊ฐ 0'์ ๊ฒฝํ์ ์ค๋๋ค.
3. ๋๊ด์ ์ ๋ฐ์ดํธ (Optimistic Update)
์๋ฒ์ ์๋ต์ด ์ค๊ธฐ๋ ์ ์ ๋ฏธ๋ฆฌ UI๋ฅผ '์ฑ๊ณต'ํ ๊ฒ์ฒ๋ผ ๋ฐ๊พธ๋ ๊ธฐ๋ฒ์ ๋๋ค. ์ข์์ ๋ฒํผ์ด๋ ๋๊ธ ์์ฑ์ฒ๋ผ ๋น ๋ฅด๊ธฐ ์ฐจ์ด๊ฐ UX์ ํฐ ์ํฅ์ ์ฃผ๋ ๊ธฐ๋ฅ์ ํ์์ ์ ๋๋ค.
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ๐ฃ ์์ฒ (ํ๋ฐ ์ด์
): "์ํธ ๋! '์์๋ค ๊ฒ์ํ' ๋ฐ์ดํฐ๋ฅผ Redux์ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋๋ผ
loading,error,success์ํ ๋ณ์๊ฐ ๊ณ์ ๋์ด๋ฉ๋๋ค. ์๋ฒ ๋ฐ์ดํฐ์ UI ์ํ๋ฅผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ค๋ค๋ ๋๋์ง ํท๊ฐ๋ ค์." - ๐ฆ ์ํธ (๋ฆฌ๋): "์์ฒ ๋, ์๋ฒ ๋ฐ์ดํฐ๋ ์ฐ๋ฆฌ๊ฐ ์์ ํ ์ํ๋ผ๊ธฐ๋ณด๋ค ์๋ฒ์ ์๊ฒฉ ์ค๋ ์ท์ ๋๋ค. ์ฐ๋ฆฌ ์ฑ ์ํ์ ๋ฌด๋ฆฌํ๊ฒ ๋ง์ถ๊ธฐ๋ณด๋ค ์บ์, ์ ์ ๋, ์ฌ๊ฒ์ฆ์ ๋ค๋ฃจ๋ ๋๊ตฌ์ ๋งก๊ธฐ๊ณ ์ปดํฌ๋ํธ๋ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ ํ๊ฒ ๋ง๋ค์ด ๋ด ์๋ค."
๋ฉด์ ์ง๋ฌธ 1. ํด๋ผ์ด์ธํธ ์ํ(Client State)์ ์๋ฒ ์ํ(Server State)๋ฅผ ๋ช ํํ ๊ตฌ๋ถํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
๐ฏ ์ถ์ ์๋
๋ฐ์ดํฐ์ ์์ ๊ถ๊ณผ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ดํดํ๊ณ ์๋์ง ํ์ธํฉ๋๋ค. ์ด๋ฅผ ๊ตฌ๋ถํ์ง ๋ชปํ๋ฉด ๋ถํ์ํ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋์ ๋ฐ์ดํฐ ๋ถ์ผ์น(Data Inconsistency) ๋ฒ๊ทธ์ ์๋ฌ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
๐ฃ ์์ฒ ์ด์ Naive ๊ตฌํ (Bad Case)
์์ฒ ์ด๋ ๋ชจ๋ API ์๋ต์ ํด๋ผ์ด์ธํธ ์ ์ญ ์คํ ์ด์ ์ง์ ๋ฃ๊ณ ์์ต๋๋ค.
// ๐ฃ ์์ฒ : "์ ์ ๋ชฉ๋ก๋ ์ ์ญ ์ํ๋๊น Redux์ ์ ์ฅํด์ผ์ง!"
function Users() {
const dispatch = useDispatch();
const { data, isLoading } = useSelector(state => state.users);
useEffect(() => {
dispatch(fetchUsers()); // โ ๏ธ ๋ก๋ฉ, ์๋ฌ, ์บ์ ๋ฌดํจํ ๋ก์ง์ ์ง์ ๋ค ๊ตฌํํด์ผ ํจ
}, []);
// โ ๏ธ ๋ฌธ์ : ๋ค๋ฅธ ํญ์์ ์ ์ ๊ฐ ์ถ๊ฐ๋์ด๋ ์ด ์ฑ์ ์ ๋ฐฉ๋ฒ์ด ์์ (Outdated)
}๐ฆ ์ํธ์ ๋ฆฌ๋ทฐ ํฌ์ธํธ
"์์ฒ ๋, ์ ์ ๋ชฉ๋ก์ ์ฐ๋ฆฌ ์ฑ์ด ์ฃผ์ธ์ด ์๋์์. ์๋ฒ๊ฐ ์ฃผ์ธ์ด์ฃ . ๋ฐ์ดํฐ๊ฐ ๋ฐ๋๋ฉด ์๋ฒ๊ฐ ์๋ ค์ฃผ๊ฑฐ๋ ์ฐ๋ฆฌ๊ฐ ๋ค์ ๋ฌผ์ด๋ด์ผ ํฉ๋๋ค. ํด๋ผ์ด์ธํธ ์ํ(๋คํฌ๋ชจ๋ ์ฌ๋ถ ๋ฑ)์๋ ์์ ํ ๋ค๋ฅธ ์ํ๊ณ์์."
๐ฆ ์ํธ์ ์ํคํ ์ฒ ๊ฐ์ด๋ (Good Case)
์ํธ ๋ฆฌ๋๋ React Query๋ฅผ ์ฌ์ฉํด ์ ์ธ์ ์ผ๋ก ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
// ๐ฆ ์ํธ: "๋ฐ์ดํฐ ํ์นญ์ '๋ช
๋ น'์ด ์๋๋ผ '์ ์ธ'์
๋๋ค."
function Users() {
// โ
๋ก๋ฉ, ์๋ฌ, ๋ฐ์ดํฐ, ์ ์ ๋ ์ฒดํฌ๊น์ง ํ ์ค๋ก ํด๊ฒฐ
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
staleTime: 1000 * 60 * 5, // 5๋ถ ๋์์ ์ ์ ํ ๋ฐ์ดํฐ๋ก ๊ฐ์ฃผ (์บ์ ํ์ฉ)
});
if (isLoading) return <Spinner />;
return <div>{data.map(user => <div key={user.id}>{user.name}</div>)}</div>;
}์ด ์ฝ๋๋ ๋ฐ์ดํฐ๋ฅผ "๊ฐ์ ธ์ค๋ผ"๊ณ ๋ช
๋ นํ๊ธฐ๋ณด๋ค ['users']๋ผ๋ ํค์ ์๋ฒ ์ค๋
์ท์ ๊ตฌ๋
ํ๋ค๊ณ ์ ์ธํฉ๋๋ค. ๊ฐ์ ํค๋ฅผ ์ฐ๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ ์บ์์ ์งํ ์ค์ธ ์์ฒญ์ ๊ณต์ ํ๋ฏ๋ก ๋ก๋ฉ, ์๋ฌ, ์ค๋ณต ์์ฒญ ์ฒ๋ฆฌ๋ฅผ ๋งค๋ฒ ๋ค์ ๋ง๋ค ํ์๊ฐ ์ค์ด๋ญ๋๋ค.
๐ ๋ ๋ฒจ๋ณ ๋ต๋ณ ๊ฐ์ด๋ (Self-Check)
- Level 1 (Junior): "์๋ฒ ์ํ๋ API๋ก ๊ฐ์ ธ์ค๋ ๋ฐ์ดํฐ๊ณ , ํด๋ผ์ด์ธํธ ์ํ๋ UI์ฉ ๋ฐ์ดํฐ์ ๋๋ค. ์๋ฒ ๋ฐ์ดํฐ๋ ๋ก๋ฉ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค."
- Level 2 (Senior): "์์ ๊ถ(Ownership)์ ์ฐจ์ด๋ฅผ ์ค๋ช ํฉ๋๋ค. ์๋ฒ ์ํ๋ ๋น๋๊ธฐ์ ์ด๊ณ ๋๊ธฐํ๊ฐ ํ์ํ๋ฉฐ ์ฌ๋ฌ ์ฌ์ฉ์๊ฐ ๊ณต์ ํ๋ค๋ ์ ์ ์ง์ ํฉ๋๋ค. ์ด๋ฅผ ์ํด ์บ์ฑ, ์ค๋ณต ์์ฒญ ๋ฐฉ์ง, ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฐ์ดํธ ๋ฑ์ด ํ์ํจ์ ๊ฐ์กฐํฉ๋๋ค."
- Level 3 (Specialist): "์๋ฒ ์ํ ๊ด๋ฆฌ๊ฐ ๋ณต์กํ ๋น์ฆ๋์ค ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ด๋ป๊ฒ 'SSOT(Single Source of Truth)' ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋์ง ๋ถ์ํฉ๋๋ค. ์๋ฒ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฆฌ์กํธ์ '์ ์ธ์ UI' ํจ๋ฌ๋ค์๊ณผ ์ด๋ป๊ฒ ์ผ์นํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ก ์ธํด ์ ์ญ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ญํ ์ด '์์ UI ์ํ'๋ก๋ง ์ถ์๋๋ ์ํคํ ์ฒ์ ์ฐ์ํจ์ ์ค๋ช ํฉ๋๋ค."
๋ฉด์ ์ง๋ฌธ 2. staleTime๊ณผ gcTime์ ์ฐจ์ด๋ฅผ ์ค๋ช ํ๊ณ , ์ด๋ฅผ ํ์ฉํ ์ต์ ์ ์บ์ ์ ๋ต์ ์ ์ํด ๋ณด์ธ์.
๐ฏ ์ถ์ ์๋
React Query์ ํต์ฌ ๋งค์ปค๋์ฆ์ธ '์ ์ ๋'์ '๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ'๋ฅผ ์ ํํ ์ดํดํ๊ณ ์ํฉ์ ๋ง๊ฒ ํ๋ํ ์ ์๋์ง ํ์ธํฉ๋๋ค.
๐ฃ ์์ฒ ์ด์ Naive ๊ตฌํ (Bad Case)
์์ฒ ์ด๋ ๋ชจ๋ API ์์ฒญ์ ๋ํด ๊ธฐ๋ณธ ์ค์ ๋ง ์ฐ๊ณ ์์ต๋๋ค.
// ๐ฃ ์์ฒ : "์ค์ ๊ฐ์ด ๋๋ฌด ๋ง์์ ๊ทธ๋ฅ ๊ธฐ๋ณธ์ผ๋ก ์จ์. ์์์ ์ ๋๊ฒ ์ฃ ?"
const { data } = useQuery({ queryKey: ['posts'], queryFn: fetchPosts });
// โ ๏ธ ๋ฌธ์ : ํ์ด์ง๋ฅผ ์ ๊น ๋๊ฐ๋ค ์ฌ ๋๋ง๋ค ๋งค๋ฒ API ์ฌํธ์ถ ๋ฐ์ (์๋ฒ ๋ถํ)๐ฆ ์ํธ์ ๋ฆฌ๋ทฐ ํฌ์ธํธ
"์์ฒ ๋, ๊ฒ์๊ธ ๋ชฉ๋ก์ ๋ณดํต 1์ด๋ง๋ค ๋ฐ๋์ง ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ๋งค๋ฒ ์๋ฒ์ ๋ค์ ๋ฌผ์ผ๋ฉด ์ฌ์ฉ์๋ ์๋ฒ๋ ๋ถํ์ํ ๋น์ฉ์ ์น๋ฌ์. ๋ฐ์ดํฐ๋ฅผ ์ผ๋ง๋ '์ ์ (Fresh)'ํ๋ค๊ณ ๋ฏฟ์ด์ค์ง ๊ฒฐ์ ํ๋ ๊ฒ ์๋์ด์ ์ธ์ฌํจ์ ๋๋ค."
๐ฆ ์ํธ์ ์ํคํ ์ฒ ๊ฐ์ด๋ (Good Case)
์ํธ ๋ฆฌ๋๊ฐ ์ํฉ์ ๋ฐ๋ฅธ ์บ์ ์ค์ ๋ฒ์ ์ ์ํฉ๋๋ค.
// ๐ฆ ์ํธ: "๋ฐ์ดํฐ์ ์ฑ๊ฒฉ์ ๋ฐ๋ผ ์ ํต๊ธฐํ์ ์ ํ์ธ์."
// 1. ๊ณต์ง์ฌํญ: ์ ์ ๋ณํจ -> staleTime์ ๊ธธ๊ฒ (์: 1์๊ฐ)
const noticeQuery = useQuery({
queryKey: ['notices'],
queryFn: fetchNotices,
staleTime: 1000 * 60 * 60,
});
// 2. ์ค์๊ฐ ์ฑํ
: ๊ณ์ ๋ณํจ -> staleTime์ 0 (๋ง์ดํธ/ํฌ์ปค์ค ๋ฑ์์ ์ฌ๊ฒ์ฆ)
const chatQuery = useQuery({
queryKey: ['chats'],
queryFn: fetchChats,
staleTime: 0,
});
// ๐ก ํ: gcTime์ ์ฌ์ฉ๋์ง ์๋ ์ฟผ๋ฆฌ ์บ์๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๋ ์๊ฐ์
๋๋ค.
// ๋ณดํต staleTime๋ณด๋ค ๊ธธ๊ฒ ๋์ด, ์ ๊น ์ด๋ํ๋ค ๋์์์ ๋ ์บ์๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค.TanStack Query v5์์๋ ์์ cacheTime ์ด๋ฆ์ด gcTime์ผ๋ก ๋ฐ๋์์ต๋๋ค. staleTime์ "๋ค์ ๋ฌผ์ด๋ณผ ํ์๊ฐ ์๋๊ฐ"๋ฅผ ๊ฒฐ์ ํ๊ณ , gcTime์ "์๋ฌด๋ ๊ตฌ๋
ํ์ง ์๋ ๋ฐ์ดํฐ๋ฅผ ์ธ์ ๋ฉ๋ชจ๋ฆฌ์์ ์น์ธ ๊ฒ์ธ๊ฐ"๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
๐ ๋ ๋ฒจ๋ณ ๋ต๋ณ ๊ฐ์ด๋ (Self-Check)
- Level 1 (Junior): "
staleTime์ ๋ฐ์ดํฐ๊ฐ ์ ์ ํ ์๊ฐ์ด๊ณ ,gcTime์ ์ฌ์ฉํ์ง ์๋ ์บ์๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๋ ์๊ฐ์ ๋๋ค." - Level 2 (Senior): "๋ฐ์ดํฐ๊ฐ 'stale'ํด์ ธ๋ ์ฆ์ ์ฌ๋ผ์ง์ง ์๊ณ , ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฌ๊ฒ์ฆ(Revalidation)์ ๋์์ด ๋จ์ ์ค๋ช
ํฉ๋๋ค.
gcTime์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์๋ํ๊ธฐ ์ ๊น์ง์ ์ฌ์ ์๊ฐ์์ ๋ช ํํ ๊ตฌ๋ถํฉ๋๋ค." - Level 3 (Specialist): "์ฌ์ฉ์ ๊ฒฝํ ๊ด์ ์์
staleTime์ ๊ธธ๊ฒ ๋๊ณ mutation ์ดํinvalidateQueries๋ฅผ ์๋์ผ๋ก ํธ์ถํ๋ '์ ์ ๋ฐ์ดํฐ ๊ด๋ฆฌ' ์ ๋ต์ ์ค๋ช ํฉ๋๋ค. ๋๋prefetchQuery์ ๊ฒฐํฉํ์ฌ ๋ค์ ํ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์บ์์ ๋ฃ์ด ์ ํ ์ง์ฐ์ ์ค์ด๋ ๊ธฐ๋ฒ์ ์ ์ํฉ๋๋ค."
๐ ์ค์ ๋ณํ ์ง๋ฌธ (Related Variations)
๋ฉด์ ์ง๋ฌธ 72. ์ฟผ๋ฆฌ ๋ฌดํจํ(Invalidation)์ ์๋ ์ ๋ฐ์ดํธ(SetQueryData)์ ์ฐจ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
- ๐ฏ ์ถ์ ์๋: ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์งํค๋ ๋ ๊ฐ์ง ์ ๋ต์ ํธ๋ ์ด๋์คํ๋ฅผ ์ดํดํ๋์ง ํ์ธํฉ๋๋ค.
- ๐ก ํต์ฌ ์๋ฆฌ & ๋ต๋ณ:
Invalidate๋ "์ด ๋ฐ์ดํฐ๋ ์ํ์ผ๋ ์๋ฒ์์ ๋ค์ ๋ฐ์์!"๋ผ๊ณ ์ ์ธํ๋ ์์ ํ ๋ฐฉ์์ด๋ฉฐ, ํญ์ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฅํฉ๋๋ค. ๋ฐ๋ฉดSetQueryData๋ ์๋ฒ ์๋ต ์ ์ ์บ์๋ฅผ ์ง์ ์์ ํ๋ '๋๊ด์ ์ ๋ฐ์ดํธ'์ ์ฃผ๋ก ์ฐ์ด๋ฉฐ, ๋คํธ์ํฌ ์์ฒญ์ ํ ๋ฒ ์๋ ์ ์์ด ํจ์ฌ ๋น ๋ฆ ๋๋ค. ํ์ง๋ง ์ง์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ฌ์ค๋ฝ๊ฒ ์กฐ์ํด์ผ ํ๋ฏ๋ก ๋ณต์ก๋๊ฐ ๋๊ณ ์คํจ ์ ๋กค๋ฐฑ ๋ก์ง์ด ํ์์ ๋๋ค.
๋ฉด์ ์ง๋ฌธ 85. ๋ฌดํ ์คํฌ๋กค(Infinite Scroll) ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ๊ณ ๋ คํด์ผ ํ ํต์ฌ ์ฑ๋ฅ ํฌ์ธํธ๋?
- ๐ฏ ์ถ์ ์๋: ๋ฐ์ดํฐ ์์ด ๋์ด๋ ๋ ์๊ธฐ๋ ๋ธ๋ผ์ฐ์ ์ ํ๊ณ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์กฐํ์ํค๋ ๋ฅ๋ ฅ์ ํ์ธํฉ๋๋ค.
- ๐ก ํต์ฌ ์๋ฆฌ & ๋ต๋ณ: ์ฒซ์งธ,
useInfiniteQuery๋ฅผ ์ฌ์ฉํ์ฌpageParam๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ด์ /๋ค์ ํ์ด์ง๋ฅผ ๋งค๋๋ฝ๊ฒ ํ์นญํด์ผ ํฉ๋๋ค. ๋์งธ, ๋ ๋๋ง ์ต์ ํ์ ๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ง์์ง๋ฉด DOM ๋ ธ๋๊ฐ ๋ฌด๊ฑฐ์์ง๋ฏ๋กIntersection Observer๋ ๋ฌผ๋ก , ํ๋ฉด ๋ฐ์ ๋ ธ๋๋ฅผ ์ ๊ฑฐํ๋ '์๋์(Windowing/Virtualization)' ๊ธฐ๋ฒ์ ๋ณํํด์ผ ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ์คํฌ๋กค ์ด๋ฒคํธ ๋๋ฐ์ด์ฑ์ด๋ ์ฐ๋กํ๋ง์ ํตํด ๋ถํ์ํ API ์์ฒญ์ด ์ฐ์์ผ๋ก ๋ฐ์ํ์ง ์๊ฒ ํด์ผ ํฉ๋๋ค.
๋ฉด์ ์ง๋ฌธ 91. ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ๊ฐ์ Query๋ฅผ ํธ์ถํ ๋, ๋คํธ์ํฌ ์์ฒญ์ด ํ ๋ฒ๋ง ๋ฐ์ํ๋ ์๋ฆฌ๋?
- ๐ฏ ์ถ์ ์๋: ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ด๋ถ ์บ์ฑ ๋ ์ด์ด์ ์์ฒญ ๋ณํฉ(Request Deduplication) ๋ฉ์ปค๋์ฆ์ ์ดํดํ๊ณ ์๋์ง ํ์ธํฉ๋๋ค.
- ๐ก ํต์ฌ ์๋ฆฌ & ๋ต๋ณ: React Query๋
QueryClient๋ผ๋ ์ ์ญ ์ ์ฅ์๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ๋ชจ๋ ์ฟผ๋ฆฌ๋ ๊ณ ์ ํQueryKey๋ฅผ ์๋ณ์๋ก ์ฌ์ฉํฉ๋๋ค. ๋์ผํ ํค๋ก ์ฌ๋ฌ ๋ฒ ์์ฒญ์ด ๋ค์ด์ค๋ฉด, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ์ฌ '์งํ ์ค์ธ ์์ฒญ(Pending Promise)'์ด ์๋์ง ํ์ธํ๊ณ ์๋ค๋ฉด ๋ณ๋์ ๋คํธ์ํฌ ํธ์ถ ์์ด ํด๋น ํ๋ก๋ฏธ์ค๋ฅผ ๊ณต์ ํฉ๋๋ค. ์ด๋ฏธ ์๋ฃ๋ ๋ฐ์ดํฐ๋ผ๋ฉด ์บ์๋ ๊ฐ์ ์ฆ์ ๋ฐํํ๋ฉฐstaleTime์ ๋ฐ๋ผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฐ์ดํธ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ปดํฌ๋ํธ๊ฐ ํํธํ๋์ด ์์ด๋ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. ์๋ฒ ๋ฐ์ดํฐ๋ฅผ Zustand ๊ฐ์ ํด๋ผ์ด์ธํธ ์ ์ญ ์ํ์ ๊ทธ๋๋ก ๋ฃ์ผ๋ฉด ์ ๋ฌธ์ ๊ฐ ๋๊ธฐ ์ฌ์ด๊ฐ์?
โ
์ ๋ต: ์๋ฒ ๋ฐ์ดํฐ์ ์์ ๊ถ, ์ ์ ๋, ์ฌ๊ฒ์ฆ, ์ค๋ณต ์์ฒญ, ์๋ฌ/๋ก๋ฉ ์ํ๋ฅผ ์ง์ ๊ด๋ฆฌํด์ผ ํ๊ธฐ ๋๋ฌธ
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช : ์๋ฒ ์ํ๋ ํด๋ผ์ด์ธํธ๊ฐ ์๋ณธ์ ์์ ํ์ง ์์ต๋๋ค. ๊ทธ๋์ staleTime, refetch, invalidation, retry, background update ๊ฐ์ ์บ์ ์ ์ฑ ์ผ๋ก ๋ค๋ฃจ๋ ํธ์ด ์์ ํฉ๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ: "์ ์ญ์์ ์ฐ๋๊น ์ ์ญ store"๋ผ๋ ํ๋จ์ ๋ฐ์ดํฐ์ ์์ ๊ถ๊ณผ ์ ์ ๋ ๋ฌธ์ ๋ฅผ ๋์นฉ๋๋ค.
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: ์๋ฒ ๋ฐ์ดํฐ๋ ์ ์ฅ๋ณด๋ค ๋๊ธฐํ๊ฐ ํต์ฌ์ ๋๋ค.
Q2. staleTime๊ณผ gcTime์ ๊ตฌ๋ถํด์ ์ค๋ช
ํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
โ
์ ๋ต: staleTime์ ๋ฐ์ดํฐ๊ฐ ์ ์ ํ๋ค๊ณ ๋ณด๋ ์๊ฐ์ด๊ณ , gcTime์ ์ฌ์ฉํ์ง ์๋ ์บ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ๋ณด๊ดํ๋ ์๊ฐ์ด๋ผ ๋ชฉ์ ์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช : ๋ ๊ฐ์ ํผ๋ํ๋ฉด ๋๋ฌด ์์ฃผ refetch๋๊ฑฐ๋, ๋ฐ๋๋ก ์ค๋๋ ๋ฐ์ดํฐ๊ฐ ์ค๋ ๋ณด์ด๋ ๋ฌธ์ ๊ฐ ์๊น๋๋ค. ๋ฉด์ ์์๋ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ๋คํธ์ํฌ ๋น์ฉ ์ฌ์ด์ ๊ท ํ๊น์ง ๋งํด์ผ ํฉ๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ: ๋ ๋ค "์บ์ ์๊ฐ"์ด๋ผ๊ณ ๋ง ๋ตํ๋ฉด ์ค์ ์ค์ ์๋๋ฅผ ์ค๋ช ํ์ง ๋ชปํฉ๋๋ค.
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: ์ ์ ๋์ ๋ณด๊ด ๊ธฐ๊ฐ์ ๋ค๋ฅธ ์ถ์ ๋๋ค.
Q3. ์์ฒ ์ด์ ํ ์คํธ ํ์: ๋๊ธ ์์ฑ mutation ์ฑ๊ณต ํ ๊ฐ์ฅ ์์ฐ์ค๋ฌ์ด ์บ์ ์ฒ๋ฆฌ ๋ฐฉ์์ ๋ฌด์์ธ๊ฐ์?
โ
์ ๋ต: ๊ด๋ จ query key๋ฅผ ๋ฌดํจํํ๊ฑฐ๋ optimistic update๋ฅผ ์ ์ฉํด ๋ชฉ๋ก๊ณผ ์์ธ ํ๋ฉด์ ์ผ๊ด์ฑ์ ํ๋ณตํ๋ค
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช : mutation์ ์๋ฒ์ ๋ณํ๋ฅผ ๋ง๋ค๊ณ , ๊ธฐ์กด ์บ์๋ ๊ทธ ์๊ฐ ๋ก์์ง ์ ์์ต๋๋ค. ์ด๋ค key๊ฐ ์ํฅ์ ๋ฐ๋์ง ์ค๊ณํด์ผ ์ฌ์ฉ์๋ ์ผ๊ด๋ ํ๋ฉด์ ๋ด ๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ:
window.location.reload()๋ ๋ฌธ์ ๋ฅผ ์จ๊ธธ ๋ฟ, ์บ์ ์ ๋ต์ ์ค๊ณํ ๋ต๋ณ์ด ์๋๋๋ค. - ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: mutation ํ์๋ ์ด๋ค ์บ์๊ฐ ๋ก์๋์ง ๋ฌป์ต๋๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋์ ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ๋ด ๋ง์๋๋ก ์์ ํ ๊ฒ์ฒ๋ผ ๋ค๋ฃจ๋ ์ต๊ด์ ๋ฒ๋ ธ๋ค. ์์๋ค ๋๊ธ ๋ชฉ๋ก์ด ์๋ก๊ณ ์นจํด์ผ๋ง ๋ง์ ๋ณด์๋ ์ด์ ๋ ๊ฒฐ๊ตญ ์บ์๋ฅผ ์ค๊ณํ์ง ์๊ณ ๊ฐ๋ง ์ ์ฅํ๋ ค ํ๊ธฐ ๋๋ฌธ์ด์๋ค.
๐ก "์๋ฒ ์ํ๋ ๋ค๊ณ ์๋ ๊ฐ์ด ์๋๋ผ, ์๋ฒ์ ๊ณ์ ๋ง์ถฐ์ผ ํ๋ ์ฝ์์ด๋ค."
๋ค์๋ถํฐ๋ API ์๋ต์ store์ ๋ฃ๊ธฐ ์ ์ "์ด ๋ฐ์ดํฐ์ ์๋ณธ์ ์ด๋๊ณ , ์ธ์ ๋ก์ผ๋ฉฐ, ์ด๋ค mutation์ด ์ํฅ์ ์ฃผ์ง?"๋ฅผ ๋จผ์ ์ ์ด๋ด์ผ๊ฒ ๋ค. ์ด์ ์์ฒ ์ด ์กฐ๊ธ์ฉ ํด๋ผ์ด์ธํธ ์ฝ๋ ๋ฐ๊นฅ์ ์๊ฐ๊น์ง ๋ณด๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค.