๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

javascript

react-query ๊ฐœ๋…, ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

728x90

 

react-query ์‚ฌ์šฉ์ด์œ 

0. ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ ˆ์ด์–ด ์ „์ฒด๋ฅผ ์ถ”์ƒํ™”, ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์•ฑ ๋‚ด์˜ ์ƒํƒœ์—์„œ UI ์ƒํƒœ์—๋งŒ ์ง‘์ค‘

1. ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์บ์‹œํ•˜๊ณ , ์š”์ฒญ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜ ๋ฐ ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณต

3. ๊ธฐ์กด ๋ฏธ๋“ค์›จ์–ด๋กœ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ ์ฒ˜๋ฆฌํ–ˆ์„๋•, api ๋™์ž‘๋งˆ๋‹ค ์ƒํƒœ์™€ ์‘๋‹ต๊ฐ’์„ ์ „์—ญ์œผ๋กœ ๊ด€๋ฆฌํ–ˆ๋Š”๋ฐ

์ด๋Š” ๋น„ํšจ์œจ์ ์ž„ -> react-query๋Š” react ์ปดํฌ๋„ŒํŠธ์™€ ํ†ตํ•ฉํ•ด ๊ฐ„ํŽธํ•˜๊ฒŒ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌ

react-query์˜ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ ์ƒํƒœ ๋ถ„๋ฅ˜
  • Stale: ์„œ๋ฒ„ / ํด๋ผ์ด์–ธํŠธ์˜ ์ •๋ณด๊ฐ€ ์‹ ์„ ํ•˜์ง€ ์•Š์€ ์ƒํƒœ, ์ฆ‰ ๋™์ผํ•จ์„ ๋ณด์žฅํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ
  • Fresh: ์„œ๋ฒ„ / ํด๋ผ์ด์–ธํŠธ์˜ ์ •๋ณด๊ฐ€ ๋™์ผํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋จ, ํ•˜์ง€๋งŒ default ์„ค์ •์œผ๋กœ๋Š” staleTime์ด 0 ์ด๋ฏ€๋กœ ๋ณด์žฅ๋˜๊ธฐ๋Š” ์–ด๋ ค์›€
  • Fetching: ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘

 

Store๋Š” ์ „์—ญ์ƒํƒœ๊ฐ€ ์ €์žฅ, ๊ด€๋ฆฌํ•˜๋Š” ๊ณต๊ฐ„

๋น„๋™๊ธฐ ํ†ต์‹  ์ž์ฒด์™€ ์ด์— ์–ฝํ˜€์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ •์ฑ…๋“ค๊ณผ ํ•จ๊ป˜ Store์˜ ์—ญํ• ์ด ๋น„๋Œ€ํ•ด์ง.

๊ธฐ์กด redux์—์„œ๋Š” redux-saga, redux-thunk ๋ฏธ๋“ค์›จ์–ด๋กœ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

ํ•œ ํ”„๋กœ๋•ํŠธ์˜ api ๋™์ž‘๋งˆ๋‹ค ajax ์ƒํƒœ์™€ ์‘๋‹ต๊ฐ’์„ ๋ฐ”๋ผ๋ณด๋Š” ์ƒํƒœ๊ฐ€ ์ƒ๊น€(success, failure ๋“ฑ)

์ด๊ฒƒ๊นŒ์ง€ ์ „์—ญ ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฑด ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ์ .

-> api ๋™์ž‘๋งˆ๋‹ค ๋ฐœ์ƒํ•˜๋Š” ์ƒํƒœ๋ฅผ ์ „์—ญ์œผ๋กœ ๊ด€๋ฆฌํ•จ.

 

๋˜ํ•œ api ์‘๋‹ต์—์„œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ ์กฐ์ž‘, ๊ฐ€๊ณต๊นŒ์ง€ store์—์„œ ๋‹ด๋‹น, ๊ด€๋ จ ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœ

์ด๋Š” Store๊ฐ€ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋“œ ๋ณด๋‹จ api ํ†ต์‹ ์„ ๋‹ด๋‹นํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ณด์ž„..

 

Store์—์„œ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ ๊ฑท์–ด๋‚ด๊ณ  Client Side ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋กœ ํƒˆ๋ฐ”๊ฟˆ

API ํ†ต์‹ ๊ณผ sync๋ฅผ ๋งž์ถฐ์•ผ ํ•˜๋ฏ€๋กœ, Store ๋ฐ–์—์„œ ์„œ๋ฒ„์™€ ๊ด€๋ จ๋œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฐฉ์•ˆ ๋งˆ๋ จ

-> ๊ทธ๋Ÿฌ๋ฉด์„œ, ์„œ๋ฒ„์™€ ๊ด€๋ จ๋œ ์ƒํƒœ๋Š” ๋งˆ์น˜ ์ „์—ญ ์ƒํƒœ์ฒ˜๋Ÿผ ์‚ฌ์šฉ

 

React Query

: Server State๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, Server์™€ Client ์‚ฌ์ด ๋น„๋™๊ธฐ ๋กœ์ง๋“ค์„ ์†์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

Client์—์„œ๋Š” ์บ์‹ฑ, ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ๋ฐ ๊ด€๋ฆฌ, lazy load์™€ ๊ฐ™์€ ์ตœ์ ํ™”, ์‘๋‹ต๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ณต์œ ํ•ด์„œ ์‚ฌ์šฉํ•  ๊ฑด์ง€ ๊ณ ๋ฏผํ•ด์•ผํ•จ.

React Query๋Š” API ํ†ต์‹ ์„ ์œ„ํ•œ ์—ฌ๋Ÿฌ ํ•จ์ˆ˜๋ฅผ useQuery์™€ ๊ฐ™์€ Hook ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ œ๊ณต.

import {
  useQuery,
  useQueryClient,
  QueryClient,
  QueryClientProvider,
} from "@tanstack/react-query";

QueryClient : React Query๊ฐ€ Client์—์„œ ๊ด€๋ฆฌํ•˜๋Š” Server State๋“ค์„ Key๋ฅผ ํ†ตํ•ด ๊บผ๋‚ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

const queryClient = new QueryClient();

QueryClientProvider : component to connect and provide a QueryClient to your application

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Menus />
    </QueryClientProvider>
  );
}

useQuery

: useQuery Hook์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” Query ์š”์ฒญ์€ HTTP METHOD GET ์š”์ฒญ๊ณผ ๊ฐ™์ด

์„œ๋ฒ„์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” “์ƒํƒœ”๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

const { data } = useQuery(
  queryKey, // ์ด Query ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œํ•  ๋•Œ ์‚ฌ์šฉํ•  Unique Key (required)
  // queryKey๋กœ ์„œ๋ฒ„ ์ƒํƒœ(API Reaponse)๋ฅผ ๋กœ์ปฌ์— ์บ์‹œํ•˜๊ณ  ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. 
  fetchFn, // ์ด Query ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ Promise๋ฅผ Return ํ•˜๋Š” ํ•จ์ˆ˜ (required)
  options, // useQuery์—์„œ ์‚ฌ์šฉ๋˜๋Š” Option ๊ฐ์ฒด (optional)
);
function Menus() {
  const queryClient = useQueryClient();
  
  const {data} = useQuery({
    queryKey: ["getMenu"],
    queryFn:() =>axios.get(
        "https://jsonplaceholder.typicode.com/posts"
      ).then({ data }) => data),
    },
  });
}

 

useMutation

: ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์š”์ฒญ์‹œ, Create, Update, Delete ์š”์ฒญ๊ณผ ๊ฐ™์ด

API ํ†ต์‹ ์œผ๋กœ Server State์— Side Effect์ด ์ผ์–ด๋‚˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•œ๋‹ค.

  const mutation = useMutation({
    mutationFn: postTodo,
    onSuccess: () => {
      // Invalidate and refetch
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
  })
const { mutate } = useMutation(
    (suggest) => axios.post('/menu', { suggest }),
    {
      // Post ์š”์ฒญ์ด ์„ฑ๊ณตํ•˜๋ฉด ์œ„ useQuery์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. (invalidateQueries)
      // ๋ฐ์ดํ„ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋ฉด useQuery๋Š” ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
      onSuccess: () => queryClient.invalidateQueries('posts'),
    },
  );
return (
    <div>
      <h1> Tomorrow's Lunch Candidates! </h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}> {item.title} </li>
        ))}
      </ul>

      <button
        onClick={() =>
          mutate({
            id: Date.now(),
            title: 'Toowoomba Pasta',
          })
        }
      >
        Suggest Tomorrow's Menu
      </button>
    </div>
  );
}

์ฐธ๊ณ ๊ธ€

https://tanstack.com/query/latest/docs/react/examples/react/basic

https://tanstack.com/query/latest/docs/react/quick-start

https://techblog.woowahan.com/6339/

https://tech.kakaopay.com/post/react-query-1/

728x90