๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐Ÿค” Topic: SWR ๋˜๋Š” React Query์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ ๋ฐฐ๊ฒฝ ๋ฐ ์›์ธ

๐ŸŽˆ Why I Stopped Using Reduxโ€‹

The Problem with Single Page Applicationsโ€‹

๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์€ ์ด์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ”„๋ŸฐํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ์˜ ๋‘ ์œ„์น˜์— ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ–ˆ์Šต๋‹ˆ๋‹ค.
๋„คํŠธ์›Œํฌ ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ์บ์‹œ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์ „์—ญ์ ์œผ๋กœ ์ €์žฅํ•˜๋Š” ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์˜ ํฐ ๋ถ€๋ถ„์€ ์ด์ œ state bugs, ๋ฐ์ดํ„ฐ ๋น„์ •๊ทœํ™” ๋ฐ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋กœ ๊ณ ํ†ต๋ฐ›์ง€ ์•Š๊ณ  ๊ธ€๋กœ๋ฒŒ store๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ถ€๋‹ด์ด ๋ฉ๋‹ˆ๋‹ค. (A big part of frontend development now becomes burdened with how to maintain our global store without suffering from state bugs, data denormalization, and stale data.)

Redux is not a Cacheโ€‹

Redux ๋ฐ ์œ ์‚ฌํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์šฐ๋ฆฌ ๋Œ€๋ถ€๋ถ„์ด ๊ฒช๋Š” ์ฃผ์š” ๋ฌธ์ œ๋Š” ๋ฐฑ์—”๋“œ ์ƒํƒœ์— ๋Œ€ํ•œ ์บ์‹œ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , reducer/action์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ† ์–ด์— ์ถ”๊ฐ€ํ•˜๊ณ , ์ตœ์‹  ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ๊ธฐ์ ์œผ๋กœ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” Redux๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์€ ์ผ์„ ํ•˜๋„๋ก ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์šฐ๋ฆฌ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํฌ๊ด„์ ์ธ ์†”๋ฃจ์…˜์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์–ตํ•ด์•ผ ํ•  ํ•œ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ ์€ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ์ƒํƒœ๊ฐ€ ๊ฒฐ์ฝ” ์‹ค์ œ๋กœ ๋™๊ธฐํ™”๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๊ปํ•ด์•ผ ๊ทธ๋“ค์ด ์žˆ๋Š” ์‹ ๊ธฐ๋ฃจ(mirage)๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋ชจ๋ธ ์˜ ๋‹จ์  ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ ์ฒ˜์Œ์— ์บ์‹œ๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋™๊ธฐํ™” ์ƒํƒœ๋ฅผ ์บ์‹ฑํ•˜๊ณ  ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋ณต์žกํ•˜๋ฏ€๋กœ Redux๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ด ๋ฐฑ์—”๋“œ ์ƒํƒœ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ƒ์„ฑํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์žฌ์ƒ์„ฑํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๋ฐฑ์—”๋“œ์™€ ํ”„๋ก ํŠธ์—”๋“œ ์ฑ…์ž„ ๊ฐ„์˜ ๊ฒฝ๊ณ„๊ฐ€ ๋น ๋ฅด๊ฒŒ ํ๋ ค์ง‘๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋กœ์„œ ์šฐ๋ฆฌ๋Š” ๊ฐ„๋‹จํ•œ UI๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด Relationships and Tables ๋Œ€ํ•œ ์™„์ „ํ•œ ์ง€์‹์„ ๊ฐ€์งˆ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค . ๋˜ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๊ทœํ™”ํ•˜๋Š” ์ตœ์ ์˜ ๋ฐฉ๋ฒ•์„ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ ์ฑ…์ž„์€ ํ…Œ์ด๋ธ”์„ ์ง์ ‘ ๋””์ž์ธํ•˜๋Š” ์‚ฌ๋žŒ๋“ค, ์ฆ‰ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž๋Š” ๋ฌธ์„œํ™”๋œ API ํ˜•ํƒœ๋กœ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ์—์„œ ๋ฐฑ์—”๋“œ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์ค‘๋‹จํ•˜๊ณ  ๋Œ€์‹  ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š” ์บ์‹œ์ฒ˜๋Ÿผ ์ทจ๊ธ‰ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ์บ์‹œ์—์„œ ์ฝ๋Š” ๋‹จ์ˆœํ•œ ๋””์Šคํ”Œ๋ ˆ์ด ๋ ˆ์ด์–ด์ฒ˜๋Ÿผ ์ทจ๊ธ‰ํ•จ์œผ๋กœ์จ ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๋Š” ์ž‘์—…ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ๋” ์‰ฌ์›Œ์ง€๊ณ  ์ˆœ์ˆ˜ํ•œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋” ์‰ฝ๊ฒŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽˆ A Simpler Approach to Backend Stateโ€‹

  1. React Query
  2. SWR
  3. Apollo Client

์ฐธ๊ณ : Comparison | React Query vs SWR vs Apollo vs RTK Query

๐ŸŽˆ How and Why You Should Use React Queryโ€‹

React๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•  ๋•Œ ์ง๋ฉดํ•˜๋Š” ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ ํŒจํ„ด์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. React์—์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ global state๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ Star Wars API์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์˜ˆ์ž…๋‹ˆ๋‹ค.

import React, {useState, useEffect} from 'react';
import axios from 'axios';
// regular fetch with axios
function App() {
const [isLoading, setLoading] = useState(false)
const [isError, setError] = useState(false)
const [data, setData] = useState({});

useEffect(() => {
const fetchData = async () => {
setError(false);
setLoading(true);

try {
const response = await axios('http://swapi.dev/api/people/1/');

setData(response.data);
} catch (error) {
setError(true);
}
setLoading(false);
};
fetchData()
}, []);
return (
<div className="App">
<h1>React Query example with Star Wars API</h1>
{isError && <div>Something went wrong ...</div>}

{isLoading ? (
<div>Loading ...</div>
) : (
<pre>{JSON.stringify(data, null, 2)}
</pre>
)}
</div>
);
}
export default App;

์œ„์˜ ์ฝ”๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐ์ดํ„ฐ๋ฅผ fetchingํ•˜๊ณ  ์žˆ๋Š”์ง€์™€ ์ด๋ฏธ API์—์„œ ์˜ค๋ฅ˜ ์‘๋‹ต์„ ๋ฐ›์•˜๋Š”์ง€, ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์„ธ ๊ฐ€์ง€์˜ ๋‹ค๋ฅธ state๊ฐ€ ํ•„์š”ํ•˜๊ณ  useState์™€ useEffect hooks ๋‘˜๋‹ค ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ, React์—์„œ ๋ฐ์ดํ„ฐ fetching๊ณผ ๊ด€๋ จ๋œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ๋ฐ์ดํ„ฐ๋Š” ๋ชจ๋“  ์•ฑ ์ธ์Šคํ„ด์Šค์—์„œ ๊ณต์œ ๋˜๋ฉฐ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(Data is shared across all app instance and can be changed by other people.)
  2. ๋ฐ์ดํ„ฐ๊ฐ€ "stale"์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ƒˆ๋กœ ๊ณ ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค. (Data could be โ€œstaleโ€ and needs to be refreshed.)
  3. ์š”์ฒญ ์ž‘์—…์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ์บ์‹ฑ ๋ฐ ๋ฐ์ดํ„ฐ ๋ฌดํšจํ™” ์ฒ˜๋ฆฌ (Handle caching and invalidating data to optimize the request operation.)

๋งˆ์ง€๋ง‰์œผ๋กœ, API์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•˜๋Š” remote state์™€ ๊ฒฐํ•ฉ๋œ ํ…Œ๋งˆ ๋ฐ ์‚ฌ์ด๋“œ๋ฐ” ๊ตฌ์„ฑ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๋ณธ ์„ค์ •์„ ์ผ๋ฐ˜์ ์œผ๋กœ ์ €์žฅํ•˜๋Š” local state๋ฅผ ๊ฐ–๋Š” ๋ฌธ์ œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (Finally, there is also the problem of having the local state which commonly stores your userโ€™s preferences like theme and sidebar config coupled with the remote state which holds the data fetched from API)

//what global state commonly look like nowadays
const state = {
// local state
theme: "light",
sidebar: "off",
// remote state
followers: [],
following: [],
userProfile: {},
messages:[],
todos:[],
}

local state์™€ remote state๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์ง€ ์•Š์„๊นŒ์š”? data fetching์œ„ํ•ด ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” boilerplate ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”?

One solution would be to create your own custom hook to handle fetching and handling of data. Thatโ€™s a completely valid solution.

Another solution and one that weโ€™ll be exploring here in-depth is React Query. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ๊ฐ„๋‹จํ•œ Hooks์™€ ํ•˜๋‚˜์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ด๋Š” ๋™์‹œ์— remote data๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ (fetch), ๋™๊ธฐํ™”ํ•˜๊ณ (synchronize), ์—…๋ฐ์ดํŠธํ•˜๊ณ (update), ์บ์‹œํ•˜๋Š”(cache) ๋ฐ ๋„์›€์ด ์ค๋‹ˆ๋‹ค.

For example, letโ€™s refactor the Star Wars API example above:

import React from 'react';
import axios from 'axios';
import {useQuery} from 'react-query';
// react-query fetch with axios
function App() {
const { isLoading, error, data } = useQuery('fetchLuke', () =>
axios('http://swapi.dev/api/people/1/'))
return (
<div className="App">
<h1>React Query example with star wars API</h1>
{error && <div>Something went wrong ...</div>}

{isLoading ? (
<div>Retrieving Luke Skywalker Information ...</div>
) : (
<pre>{JSON.stringify(data, null, 2)}
</pre>
)}
</div>
);
}
export default App;

Conclusionโ€‹

React Query๋Š” remote data๋ฅผ global state์— ๋„ฃ์„ ํ•„์š”๋ฅผ ์™„์ „ํžˆ ์—†์• ์ฃผ๋Š” ๋ฐ์ดํ„ฐ ์š”์ฒญ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ํ›Œ๋ฅญํ•œ hook ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ์œ„์น˜๋ฅผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์•Œ๋ ค ์ฃผ๊ธฐ๋งŒ โ€‹โ€‹ํ•˜๋ฉด ์ถ”๊ฐ€ ์ฝ”๋“œ๋‚˜ ๊ตฌ์„ฑ ์—†์ด ์บ์‹ฑ, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์—…๋ฐ์ดํŠธ ๋ฐ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. (You just need to tell the library where you need to fetch your data, and it will handle caching, background updates, and stale data without any extra code or configuration.)

๋˜ํ•œ React Query๋Š” useState๋ฐ useEffect hooks์˜ ํ•„์š”์„ฑ์„ ์ œ๊ฑฐํ•˜๊ณ  ๋ช‡ ์ค„์˜ React Query ๋กœ์ง์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

๐ŸŽˆ Does React Query replace Redux, MobX or other global state managers?โ€‹

  • React Query๋Š” ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๊ด€๋ฆฌ ํ•˜๋Š” Server-State ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • Redux, MobX, Zusstand ๋“ฑ์€ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Client-State ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด์ง€๋งŒ React Query์™€ ๊ฐ™์€ ๋„๊ตฌ์™€ ๋น„๊ตํ•  ๋•Œ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ ์„ ์—ผ๋‘์— ๋‘๊ณ  ์งง์€ ๋Œ€๋‹ต์€ React Query๊ฐ€ Client-State์˜ ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ ๋ฐ ๊ด€๋ จ wiring ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ช‡ ์ค„์˜ ์ฝ”๋“œ๋กœ ๋Œ€์ฒดํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์‹ค์ œ๋กœ ์—„์ฒญ๋‚œ ์–‘์˜ ๋™๊ธฐ ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ์ƒํƒœ(์˜ˆ: ๋น„์ฃผ์–ผ ๋””์ž์ด๋„ˆ ๋˜๋Š” ์Œ์•… ์ œ์ž‘ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ)๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด ์—ฌ์ „ํžˆ ์žˆ์œผ๋ฉฐ, ์ด ๊ฒฝ์šฐ ์—ฌ์ „ํžˆ Client-State ๊ด€๋ฆฌ์ž๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ React Query๋Š” local/Client State ๊ด€๋ฆฌ๋ฅผ ๋Œ€์ฒดํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ ๊ด€๋ฆฌ์ž์™€ ํ•จ๊ป˜ React Query๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽˆ ๋ฆฌ๋•์Šค ์ž˜ ์“ฐ๊ณ  ๊ณ„์‹œ๋‚˜์š”?โ€‹

API์š”์ฒญ์€ ์ด์ œ react-query, SWR์—๊ฒŒ ๋งก๊ธฐ์žโ€‹

๋ฆฌ๋•์Šค๋กœ ์š”์ฒญ์— ๊ด€๋ จ๋œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ์š”์ฒญ ์‹œ์ž‘, ์š”์ฒญ ์„ฑ๊ณต, ์š”์ฒญ ์‹คํŒจ์— ๋Œ€ํ•œ 3๊ฐ€์ง€ ์•ก์…˜๋“ค์„ ์ค€๋น„ํ•ด์•ผ ํ•˜๊ณ  ํ•ด๋‹น ์•ก์…˜๋“ค์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง๋“ค๋„ ์ค€๋น„ํ•ด์ค˜์•ผ ํ•œ๋‹ค. (ex. getEpisode, getEpisodeSuccess, getEpisodeError)

2020๋…„์—๋Š” react-query์™€ SWR ๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋ฆด๋ฆฌ์ฆˆ๋˜์—ˆ๋‹ค. ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ชจ๋‘, Hook์„ ์‚ฌ์šฉํ•˜์—ฌ API ์š”์ฒญ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ๋˜ ์บ์‹œ ๊ด€๋ฆฌ๋„ ์•„์ฃผ ๋ฉ‹์ง€๊ฒŒ ํ•ด๋‚ธ๋‹ค.

SWR์€ Next.js๋ฅผ ๋งŒ๋“  VercelํŒ€์—์„œ ๋งŒ๋“  ๊ฒƒ์ด๊ธฐ์— ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง์„ ํ•˜๋Š” ๊ฒฝ์šฐ Next.js ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค (์ ์–ด๋„ ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ํ•ด๋‹น ๋‚ด์šฉ๋งŒ ๋‹ค๋ฃฌ๋‹ค.).

๊ทธ๋Ÿผ์—๋„ ๋ฆฌ๋•์Šค ๋ฏธ๋“ค์›จ์–ด๋Š” ํ•„์š”ํ• ๊นŒ?โ€‹

ํŠน์ • ๊ธฐ๋Šฅ๋“ค์€ ๋ฏธ๋“ค์›จ์–ด์˜ ํž˜์„ ๋นŒ๋ ธ์„ ๋•Œ ๋”์šฑ ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์›น์—์„  redux-saga, ๋ชจ๋ฐ”์ผ ์•ฑ์—์„œ๋Š” redux-observable์„ ์‚ฌ์šฉํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฒซ๋ฒˆ์งธ ์ƒํ™ฉ์€ ์š”์ฒญ์„ ์—ฐ๋‹ฌ์•„์„œ ์—ฌ๋Ÿฌ๋ฒˆ ํ•˜๊ฒŒ ๋  ๋•Œ ์ด์ „ ์š”์ฒญ์€ ๋ฌด์‹œํ•˜๋„๋ก ํ•˜๊ณ  ๋งจ ๋งˆ์ง€๋ง‰์˜ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•  ๋•Œ ๋กœ ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—” redux-saga ์—์„  takeLatest, redux-observable ์—์„  switchMap ์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„์ฃผ ์‰ฝ๊ฒŒ ๋งˆ์ง€๋ง‰ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๊ตฌํ˜„์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‘๋ฒˆ์งธ ์ƒํ™ฉ์€ ์ฒซ๋ฒˆ์งธ ์ƒํ™ฉ์™€ ๊ฝค๋‚˜ ๋น„์Šทํ•œ๊ฑด๋ฐ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋์„ ๋•Œ ์ด์ „์— ์‹œ์ž‘ํ•œ ์š”์ฒญ์„ ์ทจ์†Œํ•˜๋Š” ์ƒํ™ฉ์ด๋‹ค.

์„ธ๋ฒˆ์งธ ์ƒํ™ฉ์€ ํŠน์ • ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์›ํ•˜๋Š” ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜ ๋์„ ๋•Œ ํ˜ธ์ถœํ•˜๋„๋ก ๋“ฑ๋ก์„ ํ•˜๋Š” ์ƒํ™ฉ์ด๋‹ค.

๋„ค๋ฒˆ์งธ ์ƒํ™ฉ์€ ์ปดํฌ๋„ŒํŠธ ๋ฐ–์—์„œ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์ด๋‹ค.

๐ŸŽˆ React Query ์‚ดํŽด๋ณด๊ธฐโ€‹

React Query๊ฐ€ ๋งŒ๋“ค์–ด์ง„ ๋™๊ธฐโ€‹

React ์ž์ฒด๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์นญํ•ด์˜ค๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์›๋ž˜ React ๊ฐœ๋ฐœ์ž๋“ค์€ ๊ฐ์ž์˜ ๋ฐฉ์‹์œผ๋กœ http ํ†ต์‹  ๋กœ์ง์„ ์งœ์•ผ ํ–ˆ๋‹ค.

Redux ๊ฐ™์€ ์ „์—ญ ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ’์— ๋Œ€ํ•ด์„œ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ, ์„œ๋ฒ„ ์ƒํƒœ์— ๋Œ€ํ•ด์„œ๋Š” ๊ทธ๋ ‡๊ฒŒ ์ž˜ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค. Server State๋Š” Client State์™€ ์™„์ „ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ์ž„์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋ช…์‹œ์ ์œผ๋กœ fetching์„ ์ˆ˜ํ–‰ํ•ด์•ผ๋งŒ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋กœ ์ „ํ™˜๋œ๋‹ค.
  • ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์€ ์ตœ์†Œํ•œ์œผ๋กœ ์ค„์ด๋Š”๊ฒŒ ์ข‹์€๋ฐ, ๋ณต์ˆ˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•ด fetching์„ ์—ฌ๋Ÿฌ๋ฒˆ ์ˆ˜ํ–‰ํ•˜๋Š” ๋‚ญ๋น„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ข‹์•„๋ณด์ด๋Š” ์ โ€‹

  • ๋น„๋™๊ธฐ ๊ด€๋ จํ•œ ํƒ€์ดํ•‘์ด ์ •๋ง ๋งŽ์ด ์ค„์–ด๋“ ๋‹ค
  • Redux๊ฐ™์€ ์ „์—ญ ์ƒํƒœ ์ €์žฅ์†Œ์˜ store์— ๋™๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๋Š” ๋ฐ์ดํ„ฐ์™€ ์•ก์…˜๋งŒ ๋‚จ๊ธธ ์ˆ˜ ์žˆ์–ด ํฌ๊ธฐ๋ฅผ ์ค„์ด๊ณ , Saga๋Š” ์•„์˜ˆ ๋Œ€์ฒดํ•ด๋ฒ„๋ฆฐ๋‹ค.
  • ์บ์‹ฑ๊ณผ ๋ฆฌํŒจ์นญ์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ์•Œ์•„์„œ ์ง€์›ํ•œ๋‹ค.
  • ํ’๋ถ€ํ•œ ์˜ต์…˜์„ ์ œ๊ณตํ•ด ๊ต‰์žฅํžˆ ๋งŽ์€ ๋ถ€๋ถ„์—์„œ custom์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ“Œ ์ฐธ๊ณ  ๋งํฌโ€‹