๐Ÿ“ก 05. ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ๊ณผ ์บ์‹œ ๋ฌดํšจํ™”: `useMutation`๊ณผ `invalidateQueries`

2026๋…„ 3์›” 4์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” Mutation์˜ ๊ธฐ์ดˆ์™€, ์ˆ˜์ • ํ›„ ํด๋ผ์ด์–ธํŠธ ์บ์‹œ๋ฅผ ์Šค๋งˆํŠธํ•˜๊ฒŒ ๊ฐฑ์‹ (๋ฌดํšจํ™”)ํ•˜๋Š” invalidateQueries์˜ ์„ค๊ณ„ ์ฒ ํ•™์„ ๋ฐฐ์›๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ

"์˜์ฒ  ๋‹˜, ์„œ๋ฒ„์— ์ข‹์•„์š” ๋ฐ˜์˜์€ ์ž˜ ๋๋Š”๋ฐ ์™œ ํ™”๋ฉด์€ ์ƒˆ๋กœ๊ณ ์นจ์„ ๋ˆŒ๋Ÿฌ์•ผ๋งŒ ํ•˜ํŠธ๊ฐ€ ๋นจ๊ฐ›๊ฒŒ ๋ณ€ํ•˜์ฃ ?"

โ˜•๏ธ ์˜์ฒ ์ด์˜ ๊ณ ๋ฏผ: "๋ฐ์ดํ„ฐ๋Š” ๋ฐ”๊ฟจ๋Š”๋ฐ ํ™”๋ฉด์ด ์•ˆ ๋ฐ”๋€Œ์–ด์š”!"

(ํ™”์š”์ผ ์˜คํ›„, F5(์ƒˆ๋กœ๊ณ ์นจ) ํ‚ค๋ณด๋“œ ์ƒท๊ฑด์„ ์น˜๊ธฐ ์ง์ „์ธ ์˜์ฒ )

๐Ÿฃ ์˜์ฒ : ์•„ ๋ฆฌ๋“œ ๋‹˜! ๋ฐฉ๊ธˆ fetch๋กœ '๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œํ•˜๊ธฐ' API ์˜๊ณ  200 OK ์ฝ˜์†” ์ฐํžˆ๋Š” ๊ฑฐ๊นŒ์ง€ ์™„๋ฒฝํ•˜๊ฒŒ ํ™•์ธํ–ˆ๊ฑฐ๋“ ์š”? ๊ทผ๋ฐ ์‚ญ์ œ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ ๋ฆฌ์ŠคํŠธ์—์„œ ๋ฐ”๋กœ ์•ˆ ์ง€์›Œ์ง€๊ณ  ๋–กํ•˜๋‹ˆ ๋‚จ์•„์žˆ์–ด์š”. F5 ๋ˆŒ๋Ÿฌ์„œ ์Œฉ์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจ ํ•ด์•ผ์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ๋ผ์ง„๋‹ค๋‹ˆ๊นŒ์š”? ์บ์‹œ๊ฐ€ ๋„ˆ๋ฌด ๋…ํ•œ ๊ฑฐ ์•„๋‹ˆ์—์š”?

๐Ÿฆ ์˜ํ˜ธ: ์„œ๋ฒ„(DB)์—์„œ ๊ธ€์„ ์ง€์šฐ๋Š” ํ–‰์œ„(Mutation)๋Š” ์„ฑ๊ณตํ–ˆ์ง€๋งŒ, ์ •์ž‘ ์šฐ๋ฆฌ๊ฐ€ ๋“ค๊ณ  ์žˆ๋Š” ๋กœ์ปฌ ์บ์‹œ(์‹๋นต) ์—๊ฒŒ "์•ผ! ์ € ๊ธ€ ์ง€์›Œ์กŒ์œผ๋‹ˆ๊นŒ ๋‹ˆ ๋ฐ์ดํ„ฐ ๋ฒ„๋ฆฌ๊ณ  ์„œ๋ฒ„์—์„œ ๋‹ค์‹œ ์Šค๋ƒ…์ƒท ๋”ฐ์™€!" ๋ผ๊ณ  ๋ช…๋ น์„ ์•ˆ ๋‚ด๋ ธ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ : ์–ด... ์บ์‹œ๋Š” ์•Œ์•„์„œ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ฑฐ ์•„๋‹ˆ์—ˆ์–ด์š”?

๐Ÿฆ ์˜ํ˜ธ: "GET ์š”์ฒญ" ์บ์‹ฑ๋งŒ ์ž๋™์ด์ฃ . ์–ธ์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ€์ˆ˜๊ณ (POST, DELETE, PUT) ๊ฐฑ์‹ ํ• ์ง€๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์•Œ๋ ค์ค˜์•ผ ํ•ด์š”. useMutation๊ณผ invalidateQueries ์ฝค๋ณด๋ฅผ ๋ชจ๋ฅด๋ฉด ํ‰์ƒ ์œ ์ €ํ•œํ…Œ F5 ์ƒˆ๋กœ๊ณ ์นจ๋งŒ ๊ฐ•์š”ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: ์บ์‹œ ์„œ๋ฒ„ ๋™๊ธฐํ™”์˜ ๋ณธ์งˆ

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— ๋ณด๋‚ด์„œ ๋ณ€๊ฒฝ(Create, Update, Delete)ํ•˜๋Š” ํ–‰์œ„๋ฅผ ํ†ตํ‹€์–ด Mutation(๋Œ์—ฐ๋ณ€์ด, ๋ณ€ํ˜•) ์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๋Š” ์•ž์„œ useQuery๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์–Œ์ „ํžˆ ๊ฐ€์ ธ์˜ค๋Š”(Read) ๋ฒ•๋งŒ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ปค๋ฎค๋‹ˆํ‹ฐ ์•ฑ์—์„œ๋Š” ๊ธ€์„ ์“ฐ๊ณ , ์ง€์šฐ๊ณ , ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„  ํฌ๊ฒŒ ๋‘ ๋‹จ๊ณ„ ์˜ ์•ก์…˜์ด ํ”ผ์ฒ˜๋Ÿผ ์ด์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์„œ๋ฒ„์— ๋ณ€๊ฒฝ ์š”์ฒญ์„ ๋‚ ๋ฆฐ๋‹ค. (useMutation)
  2. ๋ณ€๊ฒฝ์ด ์™„๋ฃŒ๋˜์ž๋งˆ์ž, ๊ณผ๊ฑฐ์— ๋ถˆ๋Ÿฌ์™”๋˜ ์˜ค๋ž˜๋œ ๋ฆฌ์ŠคํŠธ ๋ฐ์ดํ„ฐ ์บ์‹œ๋ฅผ ์“ฐ๋ ˆ๊ธฐํ†ต์— ์ฒ˜๋ฐ•๊ณ  ์ตœ์‹  ๋ชฉ๋ก์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ๋” ๊ฐ•์ œํ•œ๋‹ค. (invalidateQueries)

์ด ํ๋ฆ„(Flow)์„ ์ž์œ ์ž์žฌ๋กœ ๋‹ค๋ฃจ๋Š” ๊ฒƒ์ด 5๋…„ ์ฐจ ์‹ค๋ฌด์˜ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค.


1. ์„œ๋ฒ„ ํ†ต์‹ ์˜ ๋งˆ๋ฒ•์‚ฌ: useMutation

์˜์ฒ ์ด๊ฐ€ ์งฐ๋˜ ์ฝ”๋“œ๋ฅผ ๋˜์งš์–ด ๋ด…์‹œ๋‹ค.
๋ณดํ†ต ๋ฐ”๋‹๋ผ JS์—์„œ๋Š” ๋ฒ„ํŠผ ์˜จํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ ์•ˆ์— ์Œฉ fetch๋‚˜ axios๋ฅผ ์‘ค์…” ๋„ฃ์Šต๋‹ˆ๋‹ค.

// โŒ ์˜์ฒ ์ด์˜ ์ˆœ์ง„ํ•œ ๋Œ์—ฐ๋ณ€์ด
const handleDelete = async (id) => {
  setIsLoading(true); // ์—ํœด, ๋น™๊ธ€๋น™๊ธ€ ์Šคํ”ผ๋„ˆ ๋„์šฐ๊ณ 
  try {
    await axios.delete(`/posts/${id}`);
    alert('์‚ญ์ œ ์™„๋ฃŒ!');
    // ์˜์ฒ : "๋‹ค ๋๋‚ฌ์–ด... ๊ทผ๋ฐ ํ™”๋ฉด์€ ์–ด๋–ป๊ฒŒ ๋‹ค์‹œ ๊ทธ๋ฆฌ์ง€? window.location.reload()?" ๐Ÿ’ฅ
  } catch (error) {
    alert('์‚ญ์ œ ์‹คํŒจ ใ… ใ… ');
  } finally {
    setIsLoading(false);
  }
}

์ด๊ฑธ React Query์˜ useMutation ํ›…์œผ๋กœ ๊ฐ์‹ธ๋ฉด? ์—„์ฒญ๋‚˜๊ฒŒ ์„ ์–ธ์ ์ธ ์ฝ”๋“œ๋กœ ๋ณ€์‹ ํ•ฉ๋‹ˆ๋‹ค.

// โœ… ์˜ํ˜ธ ๋ฆฌ๋“œ์˜ ์šฐ์•„ํ•œ Mutation ๋ถ„๋ฆฌ
const deletePostMutation = useMutation({
  mutationFn: (id: number) => axios.delete(`/posts/${id}`),
});
 
// ๋ฒ„ํŠผ ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ
const handleDelete = (id) => {
  deletePostMutation.mutate(id);
};
 
// ๋ Œ๋”๋ง ๋ทฐ (๋กœ๋”ฉ, ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ์ปดํฌ๋„ŒํŠธ์— ๋…น์—ฌ๋ƒ„)
return (
  <button 
    disabled={deletePostMutation.isPending} 
    onClick={() => handleDelete(1)}
  >
    {deletePostMutation.isPending ? '์‚ญ์ œ ์ค‘...' : '์‚ญ์ œ'}
  </button>
);

์šฐ๋ฆฌ๋Š” mutate๋ผ๋Š” ๋ฐฉ์•„์‡ (Trigger) ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ๋•ก๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค. isPending, isError, isSuccess ๊ฐ™์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ ์ฒ˜๋ฆฌ๋Š” ํ›…์ด ์•Œ์•„์„œ ๊ด€๋ฆฌํ•ด ์ฃผ์ฃ .

๐Ÿ’ก ์‹ฌ์ธต ํ•ด๋ถ€: mutate vs mutateAsync์˜ ์ฐจ์ด

  • mutate: ๋’ท์ผ์€ ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ์— ๋งก๊ธฐ๊ณ  ์ฝœ๋ฐฑํ•จ์ˆ˜(onSuccess, onError) ์ชฝ์— ๋กœ์ง์„ ํƒœ์šฐ๋Š” "Fire and Forget" ๋ฐฉ์‹. ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.
  • mutateAsync: ์ง์ ‘ ํŒŒ๋ฉธ์  ์—๋Ÿฌ๋ฅผ ์žก์•„์•ผ ํ•˜๊ฑฐ๋‚˜, ์ˆœ์ฐจ์  ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ๋ฌถ์„ ๋•Œ(await ๋ถ™์—ฌ์„œ) ๊ฐ•์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹. (TkDodo ์•„ํ‹ฐํด #12 ์ฐธ๊ณ )

2. ๋ถ€์‰ˆ์œผ๋ฉด ์ƒˆ๋กœ ๊ณ ์นจํ•˜๋ผ: invalidateQueries

์ž, ๋ฐฉ๊ธˆ deletePostMutation์ด ๋ฌด์‚ฌํžˆ ๋๋‚ฌ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ์‹œ๋‹ค. DB์—์„œ๋Š” ๊ธ€ ๋ฒˆํ˜ธ 1๋ฒˆ์ด ์ง€์›Œ์กŒ์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ € ํ™”๋ฉด(์ € ๋จธ๋‚˜๋จผ ์บ์‹œ ๊ธˆ๊ณ )์˜ ['posts'] ์ฟผ๋ฆฌ๋Š” ์•„์ง 1๋ฒˆ ๊ธ€์„ ๊ทธ๋“ํ•˜๊ฒŒ ํ’ˆ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ onSuccess ์ฝœ๋ฐฑ ์•ˆ์—์„œ ์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ๊บผ๋‚ด๋“  ์ „๊ฐ€์˜ ๋ณด๋„, invalidateQueries ๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

// ์ „์—ญ ์บ์‹œ ์ ‘๊ทผ์„ ์œ„ํ•œ ํด๋ผ์ด์–ธํŠธ ๋Œ€๋นต ํ˜ธ์ถœ
const queryClient = useQueryClient();
 
const deletePostMutation = useMutation({
  mutationFn: (id) => axios.delete(`/posts/${id}`),
  // ๐Ÿš€ ๋น„๊ธฐ: ์‚ญ์ œ๊ฐ€ '์„ฑ๊ณต(Success)'ํ•˜๋ฉด?
  onSuccess: () => {
    // ๐Ÿ’ก "์•ผ! ['posts'] ๋ผ๋Š” ์ด๋ฆ„ํ‘œ ๋‹ฌ๊ณ  ์žˆ๋Š” ์บ์‹œ ์‹น ๋‹ค ์‰ฐ๋‚ด๋‚˜๋Š” ๊ฑธ๋กœ ๋ฌดํšจํ™”(Invalidate)์‹œ์ผœ!"
    queryClient.invalidateQueries({ queryKey: ['posts'] });
  },
});

invalidateQueries ์˜ ๋™์ž‘ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์˜ˆ์ˆ ์ ์ž…๋‹ˆ๋‹ค.

  1. ['posts'] ํ‚ค๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  ์ฟผ๋ฆฌ ์บ์‹œ๋ฅผ ์ฆ‰์‹œ ์ƒํ•œ(Stale) ์ƒํƒœ๋กœ ๊ฐ•์ œ ๋ณ€๊ฒฝ(๋งˆํ‚น)ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋งŒ์•ฝ ํ•ด๋‹น ๋ชฉ๋ก ์ปดํฌ๋„ŒํŠธ(useQuery(['posts']))๊ฐ€ ํ™”๋ฉด ์–ด๋”˜๊ฐ€์— ๋งˆ์šดํŠธ(Active)๋˜์–ด ๋„์›Œ์ ธ ์žˆ๋‹ค๋ฉด?
  3. "์–ด๋ผ? ๋‚˜ ๋ฐฉ๊ธˆ ์ƒํ–ˆ๋„ค? ๋‹ค์‹œ ์ตœ์‹  ๋ฐ์ดํ„ฐ ๋”ฐ์™€์•ผ์ง€!" ํ•˜๊ณ  ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ฆฌํŒจ์นญ(Refetching)์„ ์ž๋™ ํญ๋ฐœ ์‹œํ‚ต๋‹ˆ๋‹ค.
  4. ์‚ฌ์šฉ์ž๋Š” ๋ฒ„ํŠผ ํด๋ฆญ ํ›„(์•ฝ๊ฐ„์˜ pending...), ์“ฑ- ํ•˜๊ณ  ๋ฆฌ์ŠคํŠธ์—์„œ ์‚ญ์ œ๋œ ์ตœ์‹  ๋ ˆ์ด์•„์›ƒ์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ๋ธŒ๋ผ์šฐ์ € ํฐ ํ™”๋ฉด(F5)์€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค!

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์™€... ์˜ค๋Š˜ ์ œ๋Œ€๋กœ ํ•˜๋‚˜ ํ„ฐ๋“ํ–ˆ๋‹ค.
๋‚ด๊ฐ€ ์ˆ˜๋™์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด filter ๋Œ๋ ค์„œ ์‚ญ์ œํ•œ ๊ฐ์ฒด ์ง€์›Œ์ฃผ๊ณ , ์—๋Ÿฌ ๋‚ฌ์„ ๋• ๋กค๋ฐฑํ•˜๊ณ  ์ƒ์‘ˆ๋ฅผ ํ•˜๋˜ ์ง“๊ฑฐ๋ฆฌ๋ฅผ... ๊ทธ๋ƒฅ ์„œ๋ฒ„์—์„œ ์ง€์› ์œผ๋‹ˆ ์บ์‹œํ•œํ…Œ "๊ฐ€์„œ ๋‹ค ์—Ž์–ด๋ฒ„๋ฆฌ๊ณ  ์ตœ์‹  ๋ฆฌ์ŠคํŠธ ๋‹ค์‹œ ๋”ฐ์™€(invalidateQueries)" ๋”ฑ ํ•œ ๋งˆ๋”” ์‹œํ‚ค๋‹ˆ๊นŒ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ํ™”๋ฉด์ด ๊ฐฑ์‹ ๋๋‹ค.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "์„œ๋ฒ„ ๊ฐˆ๊ตฌ๋Š” ๋ณ€ํ–ฅ์€ useMutation์œผ๋กœ ์šฐ์•„ํ•˜๊ฒŒ ๋นผ๊ณ , ์ผ์ด ๋๋‚œ ๋’ค์—” ๋ฌด์กฐ๊ฑด invalidateQueries๋กœ ์บ์‹œํ†ต์„ ๋ฐœ๋กœ ํ•œ๋ฒˆ ๋ปฅ ์ฐจ์„œ ์ƒˆ๋กœ๊ณ ์นจ์‹œ์ผœ์ฃผ์ž!"

์‚ฌ์‹ค onSuccess ์•ˆ์—์„œ ์“ธ ๊ฑฐ๋ฉด ๊ทธ๋ƒฅ ์ปดํฌ๋„ŒํŠธ ์ƒˆ๋กœ ๋งˆ์šดํŠธ์‹œ์ผœ์ฃผ๋ฉด ์•ˆ ๋˜๋‚˜ ์†์œผ๋กœ ์ƒ๊ฐํ—€๋Š”๋ฐ, ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹ฑ๊ธ€ ํŽ˜์ด์ง€ ์•ฑ(SPA)์˜ ๋งค๋ ฅ(๋ฒˆ๋œฉ์ž„ ์—†์ด ๋ถ€๋“œ๋Ÿฌ์šด ์ „ํ™˜)์ด ์™„์ „ํžˆ ์‚ฌ๋ผ์ง€๋Š” ๊ฑฐ๊ตฌ๋‚˜. ์•„ ๋ฌดํšจํ™”... ๋ฌดํšจํ™” ์Ž„๊ฒŒ ํ•œ ํŒ ์น˜๊ณ  ์‹œ์›ํ•˜๊ฒŒ ๋งฅ์ฃผ ๋งˆ์‹œ๋Ÿฌ ๊ฐ„๋‹ค! ๐Ÿป


๐Ÿ“ ๋ฐฐ์šด ๋‚ด์šฉ ์ ๊ฒ€ํ•˜๊ธฐ (Quiz)

Q. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์˜์ฒ ์ด๊ฐ€ ํŠน์ • ๊ฒŒ์‹œ๊ธ€์˜ ์ข‹์•„์š”(Like)๋ฅผ ๋ˆ„๋ฅด๋Š” ๋Œ์—ฐ๋ณ€์ด(Mutation)๋ฅผ ๋‚ ๋ ธ์Šต๋‹ˆ๋‹ค. ์˜์ฒ ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. "๊ฒŒ์‹œ๊ธ€ ํ•˜๋‚˜์˜ ์ƒํƒœ๋งŒ ์‚ด์ง ๋ฐ”๋€ ๊ฑฐ๋‹ˆ๊นŒ ๊ตณ์ด ์„œ๋ฒ„์— ๋˜ ๋‹ค๋…€์˜ฌ ํ•„์š” ์—†์ด ํ”„๋ก ํŠธ์—”๋“œ ์ชฝ์—์„œ ์ง์ ‘ queryCache๋ฅผ ๊ฑด๋“œ๋ ค ํ•˜ํŠธ ๊ฐœ์ˆ˜๋ฅผ ์˜ฌ๋ ค๋ฒ„๋ ค์•ผ๊ฒ ๋‹ค!"

์˜ํ˜ธ์˜ ๋ฐ˜์‘๊ณผ ์กฐ์–ธ์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ์€?

  • A) "์ฒœ์žฌ์ž…๋‹ˆ๋‹ค, ์˜์ฒ  ๋‹˜! ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ์•„๋ผ๋ ค๋ฉด ํ•ญ์ƒ ๊ทธ๋ ‡๊ฒŒ ํ”„๋ก ํŠธ๋‹จ ๋กœ์ปฌ ์บ์‹œ๋ฅผ ๋œฏ์–ด๊ณ ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค."
  • B) "์•„๋‹ˆ์˜ค! ๋งŒ์•ฝ ์ข‹์•„์š” ์‘๋‹ต์ด ์˜ค๊ธฐ ์ง์ „์— ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ธ€ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ–ˆ๋‹ค๋ฉด ์–ด๋–กํ•˜๋‚˜์š”? ํ”„๋ก ํŠธ์—”๋“œ ์บ์‹œ๋Š” ์ ˆ๋Œ€ ์ˆ˜๋™ ์กฐ์ž‘ํ•˜์ง€ ๋ง๊ณ , ๋ฌด์กฐ๊ฑด invalidateQueries๋กœ๋งŒ ๊ฐฑ์‹ ํ•ด์•ผ ๋™๊ธฐํ™”๊ฐ€ ๊นจ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค."
  • C) "mutateAsync๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ˆ˜๋™์œผ๋กœ ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ปฌ ์ƒํƒœ(useState)์— ๋‹ด์•„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."

โœ… ์ •๋‹ต: B

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: TkDodo ์•„ํ‹ฐํด #10์— ๋”ฐ๋ฅด๋ฉด, QueryCache๋Š” ๋‹น์‹ ์˜ ๊ฐœ์ธ ๋กœ์ปฌ ์ƒํƒœ ๋ณ€์ˆ˜ํ‘œ๊ฐ€ ์•„๋‹ˆ๋ผ 'ํ•ญ์ƒ ์„œ๋ฒ„์˜ ์ตœ์‹  ์Šค๋ƒ…์ƒท์„ ๋—˜์˜ค๊ธฐ ์œ„ํ•œ ๊ฑฐ์šธ'์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ˆ˜์ •ํ•ด๋ฒ„๋ฆฌ๋Š” ๊ผผ์ˆ˜(setQueryData ๊ฐ•์ œ ์กฐ์ž‘ ๋“ฑ)๋ฅผ ๋‚จ๋ฐœํ•˜๋ฉด, ํ–ฅํ›„ ๋ณต์žกํ•œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ฆฌํŒจ์นญ ์‚ฌ์ดํด๊ณผ ์—‰์ผœ์„œ ๋””๋ฒ„๊น…์ด ์ฃฝ์–ด๋‚˜๋Š”(Race Condition ํญ๋ฐœ) ์ŠคํŒŒ๊ฒŒํ‹ฐ ์‹œ์Šคํ…œ์ด ๋ฉ๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: "์˜์ฒ  ๋‹˜, ๋„คํŠธ์›Œํฌ ์ฝœ ํ•œ๋ฒˆ ๋” ์˜๋Š” ๊ฒŒ ์•„๊นŒ์›Œ์„œ ์บ์‹œ๊ฐ’์„ ์ง์ ‘ ๋ฐ”๊พธ์‹œ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค! ๊ทธ๊ฑด ๋‚˜์ค‘์— ๋ฐฐ์šธ ์ง„์ •ํ•œ ๋‚™๊ด€์  ์—…๋ฐ์ดํŠธ(Optimistic Update) ์—์„œ ์ œํ•œ์ ์œผ๋กœ ์“ฐ๋Š” ๊ณ ์˜ค์˜ค๊ธ‰ ๋น„๊ธฐ๊ณ ์š”, ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ์—” ์ฟจํ•˜๊ฒŒ invalidateQueries ๋”ฑ ๋•Œ๋ ค์„œ ์„œ๋ฒ„์˜ ์ง„์งœ ๊ฒฐ๊ณผ๋ฌผ๋กœ ๋ฎ์–ด์”Œ์›Œ์•ผ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค."
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ์„ฃ๋ถ€๋ฅธ ์บ์‹œ ์ง์ ‘ ์กฐ์ž‘ ๊ธˆ์ง€! ๋ถ€์‰ˆ์œผ๋ฉด ๋ฌดํšจํ™” ๋น”(invalidate) ๋ฐœ์‚ฌ!