Redux 실제 서비스에서는 이렇게 쓴다

Jinjer·2022년 2월 27일
1
post-thumbnail

1. 프롤로그

리액트는 기본적으로 데이터 흐름이 하향식(top-down)이다
즉, 부모에서 자식으로 객체(props)를 내려주는 방식인데

간혹 부모 컴포넌트의 상태변화가 자식으로 인하여
영향을 받아야 할때도 있다

버튼 클릭 시 리스트의 아이템 생성이 대표적이다.

이때, State 끌어올리기를 사용할 수 있지만
문제는 Props drilling이 발생될 수 있다는 것.

그렇기에 공통으로 사용할 수 있는 Store를 만들어 상태를 저장하고
상태의 변화에 따라 액션을 주고 관리하는 것이 Redux이며,
이것이 Redux의 존재이유라 할 수 있다.
👏👏👏

다만 리액트만으로도 충분히 구현할 수 있다면
반드시 Redux를 사용해야만 하는 것은 아니다
불필요한 리소스를 늘려 애플리케이션을 무겁게 만들 수 있기 때문.

주어진 과제

  1. 합계금액은 공급가액과 세액을 합한 금액이어야 한다
  2. 공급가액은 단가와 수량을 곱한 금액이어야 한다
  3. 세액은 공급가액을 10으로 나눈 금액이어야 한다
  4. 품목추가 버튼을 누르면 품목 아이템이 하나 추가되어야 한다
  5. 품목아이템은 최소 4개를 유지해야 하고 최대 개수 제한은 없다
  6. Redux로 상태관리가 되어야 한다

Redux로 Store에 데이터를 저장하고 State를 변경해 보면서
Redux-Promise와 Redux-Thunk로 비동기 처리까지 적용 해보자

2. Redux

먼저, React-create-app으로 기본 세팅이 되어 있다는 전제 하에
redux 관련 의존성 패키지를 다운로드 해준다

🌱 설치

npm install redux react-redux
or
yarn add redux react-redux

React-redux란

불필요한 렌더링을 막기 위해 리액트 전용으로
최적화되어 만들어진 공식 UI 바인딩이다

주로 useDispatch와 useSelector로 Store에 데이터를 전달하고
추출할 수 있다

2-2. Redux 기본동작

Redux의 전체적인 흐름을 이해하려면
(1) 데이터를 액션형태로 만들어서 디스패치 하고

저장소(Store)는 리듀서함수로
기존 상태값에 액션으로 받은 데이터를 이용해서
(2) 변경된 상태값을 반환하는 과정을 이해해야 한다.

🙆‍♂️ 일반적인 리덕스 흐름

  1. 액션이 발생하면 액션을 디스패치 하여 스토어로 보낸다
  2. 객체 형태의 액션과 이전 State를 리듀서가 받아서 새로운 값을 반환한다
  3. 스토어는 반환된 State를 컴포넌트로 보낸다

2-3. Store

Redux의 저장소는 단일저장소로
저장소 제한이 없는 MobX와는 다르지만 역할은 동일하다

저장소(Store)의
제일 중요한 두 가지 기능을 알아두자

getState()
저장소의 현재 상태 트리를 반환한다.

dispatch(action)
상태 변경을 위한 액션을 보낸다.

2-4. Reducer

Reducer는 순수함수이다
즉, 동일한 인자를 받아서 같은 결과를 반환해야하고
사이드이펙트가 발생해서도 안된다

인자로 받은 action의 type을 감지하여
이전 state에 변화를 주고
새로운 state를 반환하게 된다

2-5. Middleware

외부 데이터를 받아서 컴포넌트에 보여줘야 할 때
비동기처리가 필요하다면 미들웨어를 사용할 수 있다

🙆‍♂️ 미들웨어가 추가된 리덕스 흐름

  1. 액션이 발생하면 액션을 디스패치 하여 미들웨어로 보낸다
  2. 비동기 작업을 수행하고 결과를 스토어로 보낸다
  3. 객체 형태의 액션과 이전 State를 리듀서가 받아서 새로운 값을 반환한다
  4. 스토어는 반환된 State를 컴포넌트로 보낸다

미들웨어인 Redux-thunk는 함수형태의 정보를 전달하고
Redux-promise는 promise형태의 정보를 Store로 전달할 수 있도록 만들어졌다
만약 둘 다 해당이 안된다면 Reducer에게 넘겨주도록 되어있다.

📁 src/index.js

import ReduxThunk from "redux-thunk";
import promiseMiddleware from "redux-promise";

const store = createStore(
   rootReducer,
   applyMiddleware(promiseMiddleware, ReduxThunk)
);

만들어진 저장소에 연결하면 된다
자세한건 다음편에서 집중적으로 다뤄보도록 하겠다

3. Redux 개발자도구

브라우저에서 Redux 환경의 개발을 도와주는
개발자도구를 설치해보자

🌱 설치

npm install redux-devtools-extension
or
yarn add redux-devtools-extension

브라우저에서도 확장 프로그램을 설치해야 된다
chrome은 웹 스토어에서 다운로드 받을 수 있다

📁 src/index.js

import {composeWithDevTools} from "redux-devtools-extension";

const store = createStore(
   rootReducer,
   composeWithDevTools() // 개발자도구 활성화
);

Store에 설정까지 추가하였다면
브라우저에서 개발자도구(F12)를 열고 확인해본다

4. persistor

Redux의 Store는 새로고침을 하거나 새창을 열면
저장되었던 데이터가 초기화 되어 버린다😤

persistor는 Store에 있는 데이터를 브라우저의 Storage에 담아두고
브라우저가 다시 랜더링 될때 그대로 가져와서 데이터를 유지 할 수 있다

🌱 설치

npm install redux-persist
or
yarn add redux-persist

persistConfig를 하나 만들고 Storage에 담을 옵션을 지정한 뒤
persistReducer를 이용해서 만들어 둔 rootReducer와 연결한다

📁 src/modules/index.js

import {combineReducers} from "redux";
import {persistReducer} from "redux-persist";
import storage from "redux-persist/lib/storage";

const persistConfig = {
   key: "root",
   whitelist: ["item", "items"],
   storage
};

const appReducer = combineReducers({
   item,
   items
});

const rootReducer = (state, action) => {
   return appReducer(state, action);
};

export default persistReducer(persistConfig, rootReducer);

이제 createStore로 생성된 Store에 rootReducer를 담아
persistStore로 연결시켜주면 된다

📁 src/index.js

import { persistStore } from "redux-persist";
import { PersistGate } from "redux-persist/integration/react";
import rootReducer from "./modules"

const store = createStore(
  rootReducer,
  ...   
);

const persistor = persistStore(store);

ReactDOM.render(
 <React.StrictMode>
   <Provider store={store}>
       <PersistGate loading={null} persistor={persistor}>
           <App />
       </PersistGate>
   </Provider>
 </React.StrictMode>,
 document.getElementById('root')
);

4-1. cryptoJS

persistor로 Storage에 데이터를 저장했으나
Local Storage와 Session Storage는 보안에 취약하다
특히 사용자의 민감정보나 로그인 정보(access Token)를 담는 경우
반드시 암호화 작업이 필요하다

🌱 설치

npm install crypto-js 
or
yarn add crypto-js

암호화 표준의 JavaScript 라이브러리인 crypto-js를 사용해 보겠다
persistConfig에 transforms 옵션을 추가하여 암호화 설정을 할 수 있다

📁 src/modules/index.js

import CryptoJS from "crypto-js"

const privateKey = "key12!#"; // 복호화 키 지정

const encrypt = createTransform(
   (inboundState) => { 
     //암호화 설정
     return ...
   },
   (outboundState) => {
     // 복호화 설정
     return ...
   }
);

const persistConfig = {
   ...
   ...
   transforms: [encrypt], // 암호화 설정
   storage
};

5. 전체 예제 코드

https://github.com/mujaen/redux-thunk

6. 정리

✔ Redux의 기본적인 사용방법에 대해 알 수 있다
✔ Store, Reducer, Middleware의 역할에 대해 알아보았다
✔ State에 접근할 때 useDispatch, useSelector를 쓸 수 있다
✔ Storage에 담을 민감정보는 암호화 해야 한다

profile
프론트엔드개발자

0개의 댓글