๐Ÿ“ก 02. ํ•ต์‹ฌ ๋ฐ์ดํ„ฐ ํŽ˜์นญ: `useQuery` ์™„๋ฒฝ ๊ฐ€์ด๋“œ

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

๐Ÿ“‹ ๊ฐœ์š”

Query Key์˜ ๋ฐฐ์—ด ์ปจ๋ฒค์…˜๋ถ€ํ„ฐ status์™€ fetchStatus์˜ ์ฐจ์ด๊นŒ์ง€, useQuery์˜ ๊ธฐ๋ณธ ๋™์ž‘ ์›๋ฆฌ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ†ต์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ

"์˜์ฒ  ๋‹˜, ๋ฐ์ดํ„ฐ๊ฐ€ ๋กœ๋”ฉ ์ค‘์ผ ๋•Œ ์Šคํ”ผ๋„ˆ๊ฐ€ ์•ˆ ๋œฌ๋‹ค๊ณ ์š”? status๋ž‘ fetchStatus์˜ ์ฐจ์ด๋ฅผ ์•„์ง ๋ชจ๋ฅด์‹œ๋Š”๊ตฐ์š”."

โ˜•๏ธ ์˜์ฒ ์ด์˜ ๊ณ ๋ฏผ: "์Šคํ”ผ๋„ˆ๊ฐ€ ๋Œ์•„๊ฐ€๋‹ค ๋ง๋‹ค ํ•˜๋Š”๋ฐ์š”?"

(์ˆ˜์š”์ผ ์˜ค์ „, ์ƒˆ๋กœ๊ณ ์นจ ๋ฒ„ํŠผ์„ ์—ฐํƒ€ํ•˜๋ฉฐ ํ•œ์ˆจ ์‰ฌ๋Š” ์˜์ฒ )

๐Ÿฃ ์˜์ฒ : ์•„... ๋ฏธ์น˜๊ฒ ๋„ค. ์ฒ˜์Œ์— ํŽ˜์ด์ง€ ๋“ค์–ด์˜ฌ ๋•Œ๋Š” "๋กœ๋”ฉ ์ค‘..." ์Šคํ”ผ๋„ˆ๊ฐ€ ์ž˜ ๋Œ๊ฑฐ๋“ ์š”? ๊ทผ๋ฐ ๋˜‘๊ฐ™์€ ํŽ˜์ด์ง€์— ๋‹ค์‹œ ๋“ค์–ด์˜ฌ ๋•Œ๋Š” ์Šคํ”ผ๋„ˆ๊ฐ€ 0.1์ดˆ ๋–ด๋‹ค๊ฐ€ ํ›… ์‚ฌ๋ผ์ ธ์„œ ํ™”๋ฉด์ด ํฝํฝ ๋Š๊ฒจ ๋ณด์—ฌ์š”. ๊ทธ๋ฆฌ๊ณ  ์œ ์ € ๋ฆฌ์ŠคํŠธ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ ํ‚ค๋ฅผ ๊ทธ๋ƒฅ ๋ฌธ์ž์—ด "users" ํ•˜๋‚˜ ๋ก ์ผ๋”๋‹ˆ ์˜์ˆ˜ ๋‹˜์ด ๋ฐฑ์—”๋“œ ๋ถ€ํ•˜ ์‹ฌํ•˜๋‹ค๊ณ  ๋ญ๋ผ๊ณ  ํ•˜์‹œ๋„ค์š”.

๐Ÿฆ ์˜ํ˜ธ: ์˜์ฒ  ๋‹˜, Query Key๋ฅผ ๋ฌธ์ž์—ด๋กœ๋งŒ ๊ด€๋ฆฌํ•˜๋ฉด ๋‚˜์ค‘์— ์บ์‹œ ํŒŒํŽธํ™”๋‚˜ ์—‰๋šฑํ•œ ์บ์‹œ ํžˆํŠธ(Cache Hit)๊ฐ€ ๋ฐœ์ƒํ•ด์š”. ๊ฒŒ๋‹ค๊ฐ€ ๋ฐฉ๊ธˆ ๋ง์”€ํ•˜์‹  '์Šคํ”ผ๋„ˆ ํฝํฝ ํ˜„์ƒ'์€ isLoading๊ณผ isFetching์˜ ์ฐจ์ด๋ฅผ ์ œ๋Œ€๋กœ ๋ชฐ๋ผ์„œ ๋ฐœ์ƒํ•˜๋Š” ์ „ํ˜•์ ์ธ ์•ˆํ‹ฐ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ : ํ—‰! isLoading์ด ๊ทธ๋ƒฅ fetch ๋Œ ๋•Œ true ๋˜๋Š” ๊ฑฐ ์•„๋‹ˆ์—์š”? ๋‘ ๊ฐœ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅด์ฃ ?


๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: ์ฟผ๋ฆฌ๋ฅผ 100% ํ†ต์ œํ•˜๊ธฐ ์œ„ํ•ด

๐Ÿฆ ์˜ํ˜ธ: useQuery๋Š” ๋‹จ์ˆœํžˆ "Promise ์ฃผ๋ฉด ๋ฐ์ดํ„ฐ ์ค„๊ฒŒ" ์ˆ˜์ค€์˜ ํ›…์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ด ์•ฑ ์ „์ฒด์˜ ๋น„๋™๊ธฐ ๋„คํŠธ์›Œํฌ ์Šคํ”ผ๋„ˆ๋ฅผ ์ง€ํœ˜ํ•˜๋Š” ๊ตํ†ต ์ˆœ๊ฒฝ์ด์—์š”.

  • Query Key: ์ด ๋ฐ์ดํ„ฐํ‘œ(๋Œ€์žฅ๋ถ€)์˜ '์ด๋ฆ„ํ‘œ'์ด์ž, ๊ทธ ๋ฐ์ดํ„ฐ์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด(Dependency Array) ์—ญํ• ์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒํƒœ์˜ ์ด์›ํ™”: React Query v4(TanStack Query)๋ถ€ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ์˜ ์œ ๋ฌด(status)์™€, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋„คํŠธ์›Œํฌ์˜ ํ™œ๋™ ์œ ๋ฌด(fetchStatus)๋ฅผ ์™„์ „ํžˆ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑธ ๊ตฌ๋ถ„ํ•˜์ง€ ๋ชปํ•˜๋ฉด ์˜คํ”„๋ผ์ธ ์ƒํ™ฉ์ด๋‚˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์—…๋ฐ์ดํŠธ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž˜๋ชป๋œ ํ”ผ๋“œ๋ฐฑ์„ ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋ณธ์ ์ธ ์›๋ฆฌ๋ฅผ ๋Œ€์ถฉ ๋„˜์–ด๊ฐ€๋ฉด ๋‚˜์ค‘์— ๋ฌดํ•œ ์Šคํฌ๋กค, ๋‚™๊ด€์  ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ๋•Œ ์บ์‹œ ๊ด€๋ฆฌ์—์„œ ๋ฐ˜๋“œ์‹œ ์‚ฌ๊ณ ๊ฐ€ ํ„ฐ์ง‘๋‹ˆ๋‹ค. ์ œ๋Œ€๋กœ ํŒŒํ—ค์ณ๋ด…์‹œ๋‹ค.


1. Query Key: ๋ฐฐ์—ด ์ปจ๋ฒค์…˜๊ณผ ์˜์กด์„ฑ์˜ ๋งˆ๋ฒ•

๊ณผ๊ฑฐ(v3 ์ด์ „)์—๋Š” Query Key๋ฅผ ๋ฌธ์ž์—ด ํ•˜๋‚˜๋งŒ ๋˜์งˆ ์ˆ˜๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: useQuery('users', fetchUsers)). ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ ๋ฌด์กฐ๊ฑด ๋ฐฐ์—ด(Array) ํ˜•ํƒœ๋กœ๋งŒ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ์š”?

// โŒ ์˜์ฒ ์ด์˜ ์œ„ํ—˜ํ•œ ์ฝ”๋“œ
const { data } = useQuery(['todos', state], () => fetchTodos(state));
 
// โœ… ์˜ํ˜ธ ๋ฆฌ๋“œ์˜ ๊น”๋”ํ•˜๊ณ  ํ™•์žฅ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ
// ๊ฐ์ฒด ์•ˆ์— ๋„ฃ์–ด์„œ ์ˆœ์„œ ๋ฌด๊ด€ & ํ™•์žฅ์„ฑ ํ™•๋ณด
const { data } = useQuery({
  queryKey: ['todos', { status: state }],
  queryFn: () => fetchTodos(state)
});

๋ฐฐ์—ด์„ ์“ฐ๋Š” ์ง„์งœ ์ด์œ : ์˜์กด์„ฑ ๋ฐฐ์—ด

useEffect์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž์ธ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. React Query์˜ Query Key๋Š” ์ •ํ™•ํžˆ ๊ทธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ์š”์†Œ(์˜ˆ: state ๋ณ€์ˆ˜)๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด, React Query๋Š” ์ฆ‰๊ฐ์ ์œผ๋กœ "์–ด? ํ‚ค๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋„ค? ๊ทธ๋Ÿผ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ์ง€(Refetch)!" ๋ผ๊ณ  ํŒ๋‹จํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋‚ ๋ฆฝ๋‹ˆ๋‹ค.

๐Ÿ’ก ์‹ฌํ™” ํŒ: Query Key ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ์•„์ดํ…œ ์ˆœ์„œ๋Š” ์ค‘์š”ํ• ๊นŒ์š”?

  • ๋ฌธ์ž์—ด ๋ฐฐ์—ด ์š”์†Œ์˜ ์ˆœ์„œ๋Š” ๋ฌด์กฐ๊ฑด ์ผ์น˜ํ•ด์•ผ ๊ฐ™์€ ์บ์‹œ๋กœ ์นฉ๋‹ˆ๋‹ค. (['todos', 'all'] ๊ณผ ['all', 'todos'] ๋Š” ์™„์ „ ๋‹ค๋ฅธ ์บ์‹œ์ž…๋‹ˆ๋‹ค.)
  • ๋ฐ˜๋ฉด, ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ํ‚ค ์ˆœ์„œ ๋Š” ๋ฌด๊ด€ํ•ฉ๋‹ˆ๋‹ค. ([{ status: 'all', page: 1 }] ๊ณผ [{ page: 1, status: 'all' }] ์€ ๋™์ผํ•œ ์บ์‹œ๋กœ ์ธ์‹ํ•˜์—ฌ ๋‚ญ๋น„๋ฅผ ๋ง‰์•„์ค๋‹ˆ๋‹ค.)

2. Promise๋ฅผ ์บ์‹ฑํ•˜๋Š” Query Function (queryFn)

queryFn์€ ๋ฐ˜๋“œ์‹œ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋Œ€๋ถ€๋ถ„์˜ ์ฃผ๋‹ˆ์–ด ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋“ค์ด ์—ฌ๊ธฐ์„œ ๊ฒช๋Š” ์˜ค๋ฅ˜๋Š” "ํ•จ์ˆ˜ ์ž์ฒด๋ฅผ ๋˜์ง€์ง€ ์•Š๊ณ , ํ•จ์ˆ˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋˜์ง€๋Š”" ์‹ค์ˆ˜์ž…๋‹ˆ๋‹ค.

// โŒ ์˜์ฒ ์ด์˜ ํ”ํ•œ ์‹ค์ˆ˜ 1 (๋‹จ์ผ ์‹คํ–‰ ํ›„ ํญ๋ฐœ)
useQuery({
  queryKey: ['user', 1],
  queryFn: fetchUser(1) // ๐Ÿ’ฅ ์ด๊ฑด ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ '์‹คํ–‰๋œ Promise ๊ฒฐ๊ณผ๋ฌผ'์ž…๋‹ˆ๋‹ค! ๋ Œ๋”๋ง๋งˆ๋‹ค ์ฝœ๋ฐฑ ์ง€์˜ฅ ๋ฐœ์ƒ.
});
 
// โœ… ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ์‹ (๊ณ ์ฐจ ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ)
useQuery({
  queryKey: ['user', 1],
  queryFn: () => fetchUser(1) 
});

3. ๋กœ๋”ฉ ์ƒํƒœ์˜ ์ง„์‹ค: status vs fetchStatus (v4+)

๊ฐ€์žฅ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์˜์ฒ ์ด๊ฐ€ ๊ฒช์—ˆ๋˜ "์Šคํ”ผ๋„ˆ๊ฐ€ ๋Œ๋‹ค ๋ง๋‹ค ํ•œ๋‹ค"๋Š” ๋ฌธ์ œ๋Š” ์—ฌ๊ธฐ์„œ ๊ธฐ์ธํ•ฉ๋‹ˆ๋‹ค.

TanStack Query๋Š” ์ƒํƒœ๋ฅผ ๋‘ ๊ฐ€์ง€ ์ถ• ์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ๋ด…๋‹ˆ๋‹ค.

  1. status (๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”๊ฐ€?)
    • pending (์ด์ „์—๋Š” loading): ๋‚ด ์บ์‹œ์— ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹จ 1๋ฐ”์ดํŠธ๋„ ์—†๋‹ค! ์ตœ์ดˆ ํ•˜๋“œ ๋กœ๋”ฉ.
    • error: ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋‹ค ์—๋Ÿฌ ๋‚ฌ๋‹ค.
    • success: ๋‚ด ์บ์‹œ์— ์„ฑ๊ณต์ ์ธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค.
  2. fetchStatus (๋„คํŠธ์›Œํฌ๊ฐ€ ๋Œ๊ณ  ์žˆ๋Š”๊ฐ€?)
    • fetching: ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋“ , ํฌ๊ทธ๋ผ์šด๋“œ๋“  ํ˜„์žฌ fetch ํ•จ์ˆ˜๊ฐ€ ๋บ‘๋บ‘์ด ๋„๋Š” ์ค‘์ด๋‹ค.
    • paused: ๋„คํŠธ์›Œํฌ๊ฐ€ ๋Š๊ฒผ๋‹ค(์˜คํ”„๋ผ์ธ).
    • idle: ์ง€๊ธˆ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋“ค๊ณ  ์กฐ์šฉํžˆ ์‰ฌ๋Š” ์ค‘์ด๋‹ค.

๊ฒฐ๋ก : ์Šคํ”ผ๋„ˆ๋Š” ๋„๋Œ€์ฒด ์–ธ์ œ ๋„์›Œ์•ผ ํ•˜๋‚˜์š”?

๋งŒ์•ฝ ์˜์ฒ ์ด๊ฐ€ isLoading(์ฆ‰, status === 'pending')์ผ ๋•Œ๋งŒ ์ „์ฒด ํ™”๋ฉด ์Šคํ”ผ๋„ˆ๋ฅผ ๋„์šด๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค:

  • ์ฒซ ์ง„์ž… (์บ์‹œ ์—†์Œ): ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ isLoading์€ true. ์Šคํ”ผ๋„ˆ ๋น™๊ธ€๋น™๊ธ€. (์ •์ƒ)
  • ๋‘ ๋ฒˆ์งธ ์ง„์ž… (์บ์‹œ ์žˆ์Œ): ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋ฏธ ๊ฐ–๊ณ  ์žˆ์–ด์„œ ๋ฐ”๋กœ ๋ณด์—ฌ์ฃผ๋ฏ€๋กœ isLoading์€ false์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธ ์ค‘(isFetching)์ด์ฃ .
  • ์ด ๊ฒฝ์šฐ ์Šคํ”ผ๋„ˆ๊ฐ€ ์•ˆ ๋œน๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์œ ์ € ๋ˆˆ์—๋Š” ๋ฒˆ๊ฐœ์ฒ˜๋Ÿผ ์ด์ „ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณด์˜€๋‹ค๊ฐ€(์บ์‹œ ํžˆํŠธ), ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํŽ˜์นญ์ด ๋๋‚˜๋Š” ์ˆœ๊ฐ„ 0.5์ดˆ ๋’ค์— ์Šค๋ฅด๋ฅต ์ตœ์‹  ๋ฐ์ดํ„ฐ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ๋งˆ๋ฒ•์„ ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
const { data, isLoading, isFetching } = useQuery({ ... });
 
// ๐ŸŸก ํ•˜๋“œ ๋กœ๋”ฉ ์Šคํ”ผ๋„ˆ (ํ™”๋ฉด ์ „์ฒด ๋ฎ๊ธฐ): ๋‚ด ์†์— ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„์˜ˆ ์—†์„ ๋•Œ๋งŒ!
if (isLoading) return <FullPageSkeleton />;
 
// ๐Ÿ”ต ์†Œํ”„ํŠธ ๋กœ๋”ฉ ์Šคํ”ผ๋„ˆ (์ƒ๋‹จ ๊ตฌ์„ ์ชผ๊ทธ๋งฃ๊ฒŒ): ์†์— ๋ฐ์ดํ„ฐ๋Š” ์žˆ๋Š”๋ฐ, ๋’ท๋‹จ์—์„œ ๊ฐฑ์‹  ์ค‘์ผ ๋•Œ!
return (
  <div>
    {isFetching && <SmallSpinner />} {/* ํ™”๋ฉด ์ƒ๋‹จ ๊ท€ํ‰์ด์— ์‚ด์ง */}
    <ul>{data.map(item => <Item key={item.id} />)}</ul>
  </div>
);

์˜์ฒ ์•„, ์ด์ œ ์Šคํ”ผ๋„ˆ ์–ด๋–ป๊ฒŒ ๋„์›Œ์•ผ ๋˜๋Š”์ง€ ์•Œ๊ฒ ์ง€? ๋ฌด์กฐ๊ฑด ๋ฎ๋Š” ๊ฒŒ ๋Šฅ์‚ฌ๊ฐ€ ์•„๋‹ˆ๋‹ค!


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

์•„... isLoading ํ•˜๋‚˜๋กœ ์ „์ฒด ํ™”๋ฉด์„ ๋‹ค ๋ฎ์–ด๋ฒ„๋ฆฌ๋‹ˆ๊นŒ ๋ฌดํ•œ ๋ฆฌ๋ Œ๋”๋ง์ด๋‚˜ ํ™”๋ฉด ๋ฒˆ์ฉ์ž„์ด ์ƒ๊ฒผ๋˜ ๊ฑฐ๊ตฌ๋‚˜. ๋ฐ์ดํ„ฐ๊ฐ€ ์ด๋ฏธ ์žˆ๋Š”๋ฐ ์™œ ํ™”๋ฉด ์ „์ฒด๋ฅผ ๋กœ๋”ฉ์œผ๋กœ ๋ฎ๋ƒ๋Š” ์˜์ˆ™(UX ๋””์ž์ธ) ๋‹˜์˜ ์ž”์†Œ๋ฆฌ๊ฐ€ ์ด์ œ์•ผ ์ดํ•ด๋๋‹ค.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "isLoading(๋ฐ์ดํ„ฐ ์—†์Œ)๊ณผ isFetching(๋„คํŠธ์›Œํฌ ๋„๋Š” ์ค‘)์„ ๊ตฌ๋ถ„ํ•˜๋ผ. ์ดˆ๊ธฐ ์ง„์ž…์€ ๋ผˆ๋Œ€(Skeleton)๋กœ, ์žฌ๋ฐฉ๋ฌธ ์‹œ์—๋Š” ์ƒ๋‹จ ์ฌ๋งŒํ•œ ์Šคํ”ผ๋„ˆ๋กœ ์šฐ์•„ํ•˜๊ฒŒ UX๋ฅผ ์„ค๊ณ„ํ•˜์ž!"

๋‚ด์ผ ์ถœ๊ทผํ•˜์ž๋งˆ์ž isLoading ํ•˜๋‚˜๋งŒ ์“ฐ๋˜ ์ปดํฌ๋„ŒํŠธ๋“ค ์‹น ๋‹ค ์ฐพ์•„์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šคํ”ผ๋„ˆ์šฉ ์ปดํฌ๋„ŒํŠธ ์กฐ๊ฐ์œผ๋กœ ๋ถ„๋ฆฌํ•ด๋ด์•ผ์ง€. ์˜ค๋Š˜์€ ๊ทธ๋ž˜๋„ ๋œ ํ˜ผ๋‚ฌ๋‹ค. ๋„ทํ”Œ๋ฆญ์Šค ๋ด…์Šฌ๋ ˆ์ด ๋‹คํ ๋ณด๋ฉด์„œ ๋งฅ์ฃผ๋‚˜ ํ•œ ์บ” ํ•ด์•ผ์ง€! ๐Ÿบ


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

Q. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ๋‰ด์Šค๋ฅผ ์กฐํšŒํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ '์ •์น˜' ํƒญ์—์„œ '๊ฒฝ์ œ' ํƒญ์œผ๋กœ ์ด๋™ํ•  ๋•Œ, ์ฝ”๋“œ๊ฐ€ ์ตœ์‹  '๊ฒฝ์ œ' ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ฒŒ(Refetching) ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ์„ค๊ณ„ํ•ด์•ผ ํ• ๊นŒ์š”?

// ๋ฌธ์ œ ์ƒํ™ฉ
const [category, setCategory] = useState('politics');
const { data } = useQuery({
  queryKey: ['news'],
  queryFn: () => fetchNews(category)
});

โœ… ์ •๋‹ต: Query Key ๋ฐฐ์—ด ์•ˆ์— category ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์˜์กด์„ฑ ๋ฐฐ์—ด์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

const { data } = useQuery({
  queryKey: ['news', category], // ์ด ๋ถ€๋ถ„!
  queryFn: () => fetchNews(category)
});

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

  • ์›๋ฆฌ ์„ค๋ช…: React Query๋Š” queryFn ๋‚ด๋ถ€์˜ ์˜์กด์„ฑ์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋Š” ๋งˆ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ์˜ค์ง queryKey ๋ฐฐ์—ด์— ์–ด๋–ค ์š”์†Œ๋“ค์ด ๋“ค์–ด์žˆ๋Š”์ง€๋งŒ ๊ฐ์‹œํ•ฉ๋‹ˆ๋‹ค. category ์ƒํƒœ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ ์ฟผ๋ฆฌ๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋„๋ก ๋งŒ๋“ค๋ ค๋ฉด ๋ฌด์กฐ๊ฑด ๊ทธ๊ฒƒ์„ queryKey ๋ฐฐ์—ด ์š”์†Œ๋กœ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ React Query๋ฅผ ์ด์šฉํ•œ ์ƒํƒœ ๋™๊ธฐํ™”์˜ ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: "์˜์ฒ  ๋‹˜, queryFn ์•ˆ์— category ๋ณ€์ˆ˜๋ฅผ ์•„๋ฌด๋ฆฌ ๋„ฃ์–ด๋†”๋„, queryKey ๋ฐฐ์—ด ์ด๋ฆ„ํ‘œ๊ฐ€ ๊ทธ๋Œ€๋กœ ['news'] ํ•˜๋‚˜๋ฟ์ด๋ผ๋ฉด ๋ฆฌ์•กํŠธ ์ฟผ๋ฆฌ๋Š” '์–ด? ํ‚ค๊ฐ€ ๋˜‘๊ฐ™๋„ค? ๋ฐฉ๊ธˆ ์ •์น˜ ๋‰ด์Šค ์บ์‹œํ•ด ๋‘” ๊ฑฐ ๊ทธ๋Œ€๋กœ ๋˜์ ธ์ค„๊ฒŒ~' ํ•˜๊ณ  ๋„˜์–ด๊ฐ€ ๋ฒ„๋ ค์š”. ์ •์น˜ ๋ˆ„๋ฅด๊ณ  ๊ฒฝ์ œ ๋ˆŒ๋ €๋Š”๋ฐ ํ™”๋ฉด์— ๊ณ„์† ์ •์น˜๋ฉด๋งŒ ๋ณด์ผ ๊ฒ๋‹ˆ๋‹ค!"
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ์ฟผ๋ฆฌ ํŽ‘์…˜ ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๋ณ€์ˆ˜(๋งค๊ฐœ๋ณ€์ˆ˜)๋Š” ์ฟผ๋ฆฌ ํ‚ค ๋ฐฐ์—ด์˜ ์ธ์งˆ๋กœ ํ•จ๊ป˜ ๋ฌถ์–ด๋ผ!