Redux
(with Redux saga)์ React query
์ ๋ํ ์ฌ์ฉ๊ธฐ์ ๋ํด ๋น๊ตํ๋ฉด์ ๋๋์ ์ ์ ์ด๋ณด๋ ค๊ณ ํ๋ค. ๊ฐ์ธ์ ์ผ๋ก react query
๋ฅผ ๋์
ํ๋ฉด์ ๋ง์ ๋ถ๋ถ์ ๋ง์กฑํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ทธ์ชฝ์ผ๋ก biased๋ ํฌ์คํ
์ด ๋ ๊ฒ ๊ฐ๋ค.
ํ ์ํฉ
ํ์ฌ ๊ทผ๋ฌดํ๊ณ ์๋ ํ์ฌ์์๋ ์ง๊ธ๊น์ง Redux
๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค. ๋น๋๊ธฐ fetch ๋ฐ middleware๋ redux-saga
๋ฅผ ์ฌ์ฉํ๋ค. ๊ทธ๋ ๋ค๋ฉด ์ฒ์์ผ๋ก ๋์๊ฐ์ ์ด๋ป๊ฒ redux-saga
๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๋๊ฐ์ ๋ํด์ ๋จผ์ ์๊ฐ์ ํด๋ณด๋ฉด, ๊ทธ ๋น์(์ฝ 3๋
์ )๋ง ํด๋ ์ง๊ธ์ฒ๋ผ hooks
๊ธฐ๋ฐ์ ์ํ๊ด๋ฆฌ library๊ฐ
ํ๋ฐํ ์ฌ์ฉ๋๋ ์๊ธฐ๊ฐ ์๋์๋ค. ๋ฌผ๋ก ์กด์ฌ๋ ํ๊ณ ์์์ ๊ฒ์ด๋ค. ์์ ์๋ก์ด ์๋น์ค๋ฅผ ์ด๊ธฐ์ธํ
ํด์ผํ๋ ์ํฉ์์ ์ฐ๋ฆฌํ์ ๊ทธ๋์ ์ต์ ์ ์ ํ์ ํ๋ค๊ณ ์๊ฐํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ ์ฐ๋ฆฌ ํ์ฌ์ ๋ค๋ฅธ ์๋น์ค๋ mobx
๋ฅผ ์ฌ์ฉํ๊ณ ์์๋๋ฐ, ํ๋ก์ ํธ ๋ด๋ถ์์ ์ฌํ๊ฒ(?) ํํธํ๋ store
๊ด๋ฆฌ๋๋ฌธ์ ์ข๋ ์ ํํ ๋์ด์๊ณ ๊ด์ฌ์ฌ๊ฐ ๋ถ๋ฆฌ๋์ด ์๋ ์๋ก์ด ๊ฒ์ ์ํ๋๊ฒ ๊ฐ๊ธฐ๋ ํ๋ค.
React-Query ๋์ ์ด์ ์ Redux-saga์ ๋จ์
์ด์จ๋ redux-saga
์ ํจ๊ป ์๋น์ค๋ ๋ฐ์นญ๋์ด์ ํ์ฌ๊น์ง ์ ์ด์ํด์ค๊ณ ์๋ค. ํ์ง๋ง ์์ฆ ๋ค์ด์ ๊ทธ๋ ๊ฒ ์ค๋๊ธฐ๊ฐ ๋ฌธ์ ์์ด ์ฌ์ฉํ๋ redux-saga
๋ ์ฌ์ฌ ๋จ์ ๋ค์ด ๋ณด์ด๊ธฐ ์์ํ๊ณ , ๋ ์ด๋ฅผ ๋ณด์ํ ์ ์๋ ์ฌ๋ฌ๊ฐ์ง ์ ํฅ๊ฐ์๋ค์ ๋ ์ค๋ฅด๊ณ ์์๋ค. ๊ทธ๋์ redux-saga
๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋๋ ๋จ์ ๋ค์ ๋ฝ์๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- ์ ์ง๋ณด์๊ฐ ์ ๋๋ก ๋์ง ์๋๋ฏํ ๋๋
redux-saga
npm version์ ๋ณด๋ฉด ์ต๊ทผ publish๋ 14์ผ์ ์ด์ง๋ง, ์ด๊ฒ์ ๋ฐ๋ก ์ publish๋ 1๋
์ ์ด๋ค. ๊ทธ ์ ์ publish๋ 4๋
์ ์ด์๋ค. ์ผ๊ฐ์์๋ redux-saga
๋ฅผ ํฌ๊ธฐํ๊ฒ์ด ์๋๋๋ ์ฌ๋ฌ๊ฐ์ง ๋ฃจ๋จธ๊ฐ ์์๋ค. 2์ฃผ์ ์ publish๋ฅผ ๊ธฐ์ ์ผ๋ก ํ๋ฐํ ์ ์ง๋ณด์๊ฐ ๋ ๊ฒ์ธ๊ฐ ๋ํ ์๋ฌธ์ด๋ค.
- ์ฝ๋ ์์ฑ์
boilerplate
๊ฐ ๋๋ฌด ๋ง๋ค
ํ์ฌ ํ๋ก์ ํธ์์๋ redux-saga
+ redux-toolkit
์ ํจ๊ป ์ฌ์ฉํ๊ณ ์๊ณ , REQUEST
/SUCCESS
/FAILURE
ํจํด์ ์ฌ์ฉํ๊ณ ์๋ค. ํ๋ฒ์ ๋์์ ๋ํด 3๊ฐ์ง ์ผ์ด์ค๋ฅผ ๋ค ๋ง๋ค์ด์ค์ผํ๊ณ , reducer์
saga๋
3๊ฐ์ง๋ฅผ ์์ฑํด์ผํ๋ ๋ถํ์ํ ๋ฐ๋ณต์์
๊ณผ ์ค์ ๋ก ์ ๋ช
๋ฌด์คํ ์ฝ๋๋ค์ด ๋ง์๋ค.
typescript
ํธํ์ด ์ ์๋๋ค
๊ฐ์ฅ ์น๋ช
์ ์ธ ๋จ์ ์ด๋ผ๊ณ ๋ณธ๋ค. typescript
์ง์์ด ์ ๋์ง ์๊ธฐ ๋๋ฌธ์ return type
์ ํ๋๋ฐ ์ ๋ฅผ ๋จน๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
- ๊ทธ์ธ์ ์์ํ์ง๋ง ์น๋ช
์ ์ธ
error
๋ค
ํ์ฌ redux์
nextjs๋ฅผ
ํจ๊ป ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ฐ๊ฒฐํ๊ธฐ ์ํ next-redux-wrapper
library๋ ์ฌ์ฉํ๊ณ ์๋ค. ๋ค๋ฅธ ๋ถ๋ถ์ ์๊ด์ด ์์ง๋ง getServerSideProps
๋ด๋ถ์์ saga๋ฅผ callํ ๋ค์ 2๋ฒ์งธ๋ก ๋ค๋ฅธ saga๋ฅผ callํ ๋ ๋ฐ์ดํฐ๊ฐ ๊ผฌ์ด๋ ํ์์ ์ฌ์ฌ์น์๊ฒ ๋ฐ๊ฒฌํ ์ ์์๋ค. ์ ํํ ์์ธ์ ๋ชจ๋ฅด์ง๋ง ๊ทธ ์ด์๋๋ฌธ์ ์์
์ ํ ๋ ๋ช๋ฒ์ด๊ณ ์ฐํํ๋ ๊ธฐ์ต์ด ์๋ค. (๋ด๊ฐ ํด๊ฒฐ๋ฒ์ ๋ชจ๋ฅด๋๊ฒ ์ผ์๋)
๊ทธ๋์ ๋นจ๋ฆฌ redux-saga
๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋์ฒดํ์ผ๋ฉด ์ข๊ฒ ๋ค๋ ์ด์ผ๊ธฐ๊ฐ ์ ์ ๋๋๋๊ธฐ ์์ํ์๊ณ , ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์ผ์ฐ์ด ๋์
ํด์ ์ฌ์ฉํ๋ react-query
๋ฅผ ๋์
ํ๊ฒ ๋์๋ค. ๊ทธ๋ฆฌํ์ฌ ํ์ฌ ํ๋ก์ ํธ๋ redux
, redux-saga
, react-query
๊ฐ ๊ณต์กดํ๋ ์ํ๊ฐ ๋ ๊ฒ์ด๋ค.
๋์ ์์
react-query
๋ฅผ ๋์
ํ๋ฉด์ ๊ฐ์ฅ ํฐ ๊ณจ์นซ๊ฑฐ๋ฆฌ๋ ๋ฐ๋ก query key๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ์ง ์ ์ฑ
์ ์ ํ๋ ๊ฒ์ด๋ค. react-query
์์ ๋ชจ๋ data์ ๊ด๋ฆฌ์ ์์์ query key๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ ๋น์ฐํ ์ค๋ณต์ด ๋ฐ์ํ ์ฐ๋ ค๊ฐ ์๊ฑฐ๋ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์ด key ์์ฑ ์ ์ฑ
์ ํผํ์ด์ผํ๋ค. ๋ค์ํ ๋ฐฉ๋ฒ์ด ์์์ง๋ง ๊ทธ๋๋ tanstack
๋ฌธ์์๋ ๋ช
์๋์ด ์๋ query key management library
์ค ํ๋์ธ @lukemorales/query-key-factory๋ฅผ ์ฌ์ฉํ๋ค. ์ด library๋ฅผ ์ฌ์ฉํ๋ฉด์ array
ํํ๋ก ๊ตฌ์กฐํ๋ key
๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด์ ์ข๋ ์ ํฉ์ฑ์ด ๋ณด์ฅ๋๋ ํจ์จ์ ์ธ key ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ก๋ค. ๋ฌผ๋ก ์ด ์ธ์๋ ์ฌ๋ฌ๊ฐ์ง key management library๋ค์ ๋ง์ด ์์๊ฒ์ด๋ค.
์ฌ์ฉ๋ฒ์ ์ฐจ์ด
์ฌ์ค redux-saga
๋ middleware
๋ก ๋ค์ํ ์ฌ์ฉ๋ฐฉ๋ฒ์ด ์กด์ฌํ๋ค. ํ์ฌ ํ๋ก์ ํธ์์๋ redux-saga
๋ฅผ ๋น๋๊ธฐํธ์ถ์์ ๋๊ธฐ๋ฅผ ๋ณด์ฅ๋ฐ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ชฉ์ ์ด ํฌ๊ธฐ ๋๋ฌธ์ fetch
ํ response
๋ฅผ success
/failure
saga๋ก ์ ๋ฌํด์ฃผ๋ฉด์ reducer
์ ํด๋น๊ฐ์ ํ ๋นํ๋ basic
ํ ๋ฐฉ์์ ์ฌ์ฉํ๊ณ ์๋ค.
const [SUCCESS, FAILURE] = ['data_fetch_success', 'data_fetch_failure']
const getDataSaga = (payload) => {
const data = fetch_api(payload);
if(data) {
yield put({ type: SUCCESS, payload: data });
} else {
yield put({ type: FAILURE, payload: data });
}
};
ํ์ํ ๊ฒฝ์ฐ saga
์์ ์ ๊ณตํ๋ effects
๋ค์ ์ฌ์ฉํ๊ณ ์๋ค (select
, debounce
, put
, cancel
๋ฑ)
react-query
๋ ์ด์ ์ฌ์ฉ๋ฒ์ด ์ ํ ๋ค๋ฅด๋ค. ์ฐ์ ์ ์ผ ๋ค๋ฅธ์ ์ hooks
๊ธฐ๋ฐ์ library
์ด๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด react hook
์ ์ ์ฉ๋๋ rule๋ค์ ๋ฐ๋ผ์ผํ๋ค. ์ด๊ฒ์ด ์กฐ๊ธ ๊น๋ค๋ก์ด ๋ถ๋ถ์ด๊ธฐ๋ ํ๋ค. (ํนํ, rule์ค hooks
๋ ์กฐ๊ฑด๊ณผ ์๊ด์์ด ํญ์ ํธ์ถ๋์ด์ผ ํ๋ค๋ ๋ด์ฉ์ ์ถฉ์กฑํ๋๊ฒ์ด saga
๋ก์ง์์ ๋์ด์ฌ๋ ๋ง์ ๊ฑธ๋ฆผ๋์ด ๋๊ธฐ๋ ํ์๋ค)
ํ์ง๋ง react-query
๋ก๋ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ ํ๋์ ํจ์๋ก ์์ ๋ก์ง์ํ์ด ๊ฐ๋ฅํ๋ค.
const { data, isLoading, isError } = useQuery('data', fetch_api,
{
onSuccess: (data) => doSomething(data),
onError: (error) => toast.error(error.message)
// ๋จ, query์ onSuccess, onError๋ react-query v5์์ deprecated ๋์๋ค
}
);
๊ฐ๋จํ ์ฌ์ฉ๋ฒ ๋ฟ๋ง ์๋๋ผ react-query
์์ ์์ฒด์ ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ์ฌ๋ฌ๊ฐ์ง ๊ธฐ๋ณธํจ์๋ฅผ ํ์ฉํ ์ ์๋ค. (refetch
, useInfiniteQuery
, prefetching
๋ฑ). DX
์ ์ธ ์ธก๋ฉด์์๋ react query devtool
๋ํ ์ง๊ด์ ์ด๊ณ ๋ณด๊ธฐ ํธํ๊ฒ ์ ๊ณตํด์ฃผ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐ์ ํจ์จ์ ๋ ๋์ผ ์ ์๋ค. redux devtool
์ ๊ฐ์ธ์ ์ผ๋ก ๋ณด๊ธฐ๊ฐ ๋๋ฌด ์ด๋ ต๊ณ ์ฌ์ฉ๋ฒ๋ react query devtool
์ ๋นํด ์ด๋ ค์ด๊ฒ์ด ์ฌ์ค์ด๋ค.
๋ด๊ฐ ์๊ฐํ ๊ฐ์ฅ ํฐ ์ฅ์
React query
๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋๊ผ๋ ๊ฐ์ฅ ํฐ ์ฅ์ ์ด์ ์ค์ ์ฑ๋ฅ์์ผ๋ก๋ ํจ๊ณผ๋ฅผ ๋ณด์๋ค๊ณ ์๊ฐํ๋ ๋ถ๋ถ์ ๋ฐ๋ก caching
์ด๋ค. ์๋ง ๋ง์ ๊ฐ๋ฐ์๋ค์ด ์ด๊ฒ ๋๋ฌธ์ react query
๋ฅผ ๋์
์ ๊ณ ๋ คํ ๊ฒ์ด๋ค. react query
๋ ์์ฒด์ ์ผ๋ก caching
์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ง์ฝ key
๊ฐ ๋์ผํ ๊ฒฝ์ฐ ํด๋น data๋ฅผ cache
์์ ์ฐพ์์ ๊ฐ์ ธ์จ๋ค. (๋ฌผ๋ก ์กด์ฌํ๋ค๋ฉด ๋ง์ด๋ค). ์ด๋ถ๋ถ์์ ๊ฐ์ฅ ํฐ ์ด์ ์ ๋ณธ๊ฒ์ ์ ๋ณด๋ฅผ searchํ ๋์ด๋ค.
ํ์ฌ ์๋น์ค์์๋ ๊ฒ์์ํ ๋ ๋ฃ์์ ์๋ parameter๊ฐ ๊ต์ฅํ ๋ง๋ค. ๋ชจ๋ ์กฐ๊ฑด์ ๋ค ์ ํํ๊ฒ ๋๋ฉด 30๊ฐ๋ ๋์ด๊ฐ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. redux-saga
๋ฅผ ์ฌ์ฉํ์๋๋ cache
์ต์
์ ํฌ๊ฒ ๊ณ ๋ คํ์ง ์๊ณ ๊ตฌํ์ ํ์๊ธฐ ๋๋ฌธ์ 30๊ฐ ์กฐ๊ฑด์ ๊ฒ์ํ ๋ค์ ๋ ๋์ผํ ์กฐ๊ฑด์ ๊ฒ์ํ๊ฒ ๋๋ฉด ๊ทธ๋งํผ์ computing๊ณผ ์๊ฐ์ด ๊ฑธ๋ฆฌ๊ฒ ๋์๋ค. ํ์ง๋ง react query ๋์
์ดํ ๊ฐ์ ๊ฒ์์กฐ๊ฑด์ผ๋ก ๊ฒ์์ ํ ๋ค์ ๋ ๋์ผํ ์กฐ๊ฑด์ ๊ฒ์ํ๊ฒ ๋๋ฉด cache
์์ ๋ฐ๋ก ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ ์ด์ ๋งํผ์ ๋ฆฌ์์ค๊ฐ ์ฌ์ฉ๋์ง ์๋๋ค. ์ฑ๋ฅ์ ์ผ๋ก๋ ux์ ์ผ๋ก ๋ง์ ๋์์ ๋ฐ์ ๊ธฐ๋ฅ์ด๊ธฐ๋ ํ๋ค. ๋ฌผ๋ก redux-saga
์์๋ ๊ฐ๋ฅํ๊ณ ๋ด๊ฐ ์ฌ์ฉํ์ง ์์๋ ๊ธฐ๋ฅ์ผ์ง๋ ๋ชจ๋ฅธ๋ค. ํ์ง๋ง react query
์ฒ๋ผ reference๊ฐ ๋ง์ง๋ ์์๊ธฐ ๋๋ฌธ์ ๋ด๊ฐ ์ฌ์ฉํ์ง ์์์๊น ํ๊ณ ์ถ์ธกํด๋ณธ๋ค.
- https://tanstack.com/query/latest
- https://tanstack.com/query/latest/docs/react/community/community-projects#query-key-factory
- https://github.com/lukemorales/query-key-factory
- https://legacy.reactjs.org/docs/hooks-rules.html