JavaScript

상태관리 라이브러리 Redux

citron031 2022. 11. 12. 17:24

Redux는 자바스크립트 어플리케이션에서 예측 가능한 상태의 관리를 해주는 container이다.

상태 관리를 위한 전역 상태의 저장소를 제공한다.

Redux는 react의 하위 라이브러리가 아니고, 자바스크립트 어플리케이션이라면 사용이 가능하다.

컴포넌트간의 정보 공유가 필요할 때, 복잡성을 줄이기 위해서 상태관리 라이브러리인 redux를 사용한다.

// NPM 으로 설치
npm install redux

// Yarn 으로 설치
yarn add redux

참고 자료 : https://ko.redux.js.org/introduction/getting-started

 

Redux 시작하기 | Redux

소개 > 시작하기: Redux를 배우고 사용하기 위한 자료

ko.redux.js.org

Redux의 세 가지 원칙

1. Single Source Of Truth
redux에서 state는 모두 store에서 와야 한다.

2. State is read-only
state를 수정할 때는 항상 action 객체를 사용해야 한다.
🍎 setState를 사용할 때 처럼 상태를 바로 수정하면 안된다.

3. Changes are made with pure functions
reducer는 순수함수로 작성되야 한다.
side effect가 발생하면 예기치 못한 결과가 발생할 수 있다.

store

  • 상태가 관리되는 오직 단 하나의 저장소이다.
  • redux 앱의 state가 저장되어 있는 공간이다.
  • createStore 메소드를 활용해 reducer를 연결할 수 있다.
import { createStore } from 'redux';

const store = createStore(rootReducer);

Provider

  • Provider를 통해서 store를 index.js에 연결시킨다.
  • redux store 생성 후 Provider로 연결해주어야 한다.
import reducer from './redux/reducer';
import { Provider } from 'react-redux';


const store = createStore(reducer); // redux store 생성 후 Provider로 연결
// 크롬 확장 프로그램인 Redux Devtools을 사용하려면, 다음과 같이 작성한다.
// const store = createStore(reducer, 
	window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

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

action

  • simple 자바스크립트 객체이다.
  • 어떤 행동을 할 것인지 미리 정의해 놓은 객체이다.
  • type을 필수로 지정해 주어야 한다.
  • store에 저장/수정할 값을 payload로 갖는다. (운반한다)
    🧁 프로퍼티 키값의 이름은 꼭 payload일 필요는 없다.
export const ADD_ORDER = "ADD_ORDER";

export const addOrderAction = (data) => {
  return { type: ADD_ORDER, payload: data };
};

dispatch

  • action을 전달하는 함수이다.
  • dispatch의 전달인자로 action 객체가 전달된다.
  • reducer를 호출해 state의 값을 갱신한다.
  • dispatch의 인자로 action 객체를 반환하는 함수를 만들어 사용할 수도 있다.
const dispatch = useDispatch();

diapatch({ 
	type: 'counting',
    payload: {
    	"id" : 1,
        "count" : 5,
    },
});

// 기존에 만든 Action객체를 반환하는 함수를 사용한다.
dispatch(addOrderAction("APPLE"));

reducer

  • action 객체의 type에 따라서 다른 동작을 한다.
  • state와 action을 인자로 받아 새로운 state를 만들어 내는 pure function이다.
  • switch 또는 if문으로 action의 type에 따라 분기한다.
  • Redux의 state 업데이트는 immutable한 방식으로 변경해야 한다.
    (ex. Object.assign으로 새로운 객체를 만들어 return해 변경한다.)
    🌯 Redux의 장점중 하나인 변경된 state의 로그를 남기기 위해서 꼭 immutable한 방식으로 state를 업데이트해야 한다.
import { ADD_ORDER } from "../actions/ordersAction";
import { combineReducers } from "redux";

const initialState = {
  orders: [],
};

const ordersReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_ORDER:
      return { orders: [...state.orders, action.payload] };
    default:
      return state;
  }
};

export default combineReducers({ ordersReducer });

action 객체는 dispatch에게 전달되고, dispatch는 reducer를 호출해 새로운 state를 생성한다.

action dispatch -> reducer -> new state in store

🥝 데이터는 한 방향으로만 흘러야 한다.

Redux의 장점

상태를 예측 가능하게 만들어준다.

유지 보수를 쉽게 해준다.

action과 state의 log를 기록하면, 디버깅에 유리하다.
🍷 크롬의 확장 프로그램인 redux devtool을 이용하면 쉽게 확인할 수 있다.

순수함수를 이용하기 때문에, 테스트를 붙이기 쉽다.

결과적으로 redux를 이용하면 전역상태 store를 사용할 수 있고, 이를 통해 lifting state up과 props driling을 해결할 수 있다.

Action, Reducer, Dispatch, Store의 연결

Action, Reducer, Dispatch, Store을 연결하기 위해서 사용할 수 있는 두 가지 방법이 있다.
🍰 connect parameter를 통해 mapStateToProps, mapDispatchToProps 등 의 메소드를 이용한다.
🍪 useSelector나 useDispatch와 같은 Redux hooks를 이용하는 방법이 있다.

Redux hooks

redux hook의 사용을 위해서 react-redux를 설치해준다.

npm i react-redux
또는
yarn add react-redux

useSelector()

  • useSelector는 컴포넌트와 state를 연결한다.
  • useSelector 훅으로 store의 state에 접근할 수 있다.
  • useSelector는 전달인자로 콜백함수를 받는다. 이 콜백함수의 전달인자에는 state값이 들어간다.
  • 콜백함수의 전달인자인 state의 값에서 원하는 객체의 값을 return 받아 사용한다.
    🥧 모든 상태를 전달받기 위해서는 state를 return한다.
import { useSelector } from 'react-redux'
const state = useSelector(/* state를 인자로 갖는 콜백함수 */);

// state 내부에 store에 저장된 상태값들이 담긴다.

useDispatch()

  • useDispatch는 action 객체를 reducer로 전달해주는 훅이다.
  • 이벤트가 일어나는 컴포넌트에서 사용한다.
import { useDispatch } from 'react-redux'
const dispatch = useDispatch();

const handleClick(){
	dispatch(/* action object */)
}

🍑 redux-thunk / redux-saga 미들웨어를 사용하면, 동기적으로 redux architecture를 구성할 수 있다.

redux-thunk는 redux-saga에 비해서 기능이 적지만, 그만큼 가벼운 라이브러리이다.

🍑 redux-thunk 깃허브 : https://github.com/reduxjs/redux-thunk/

 

GitHub - reduxjs/redux-thunk: Thunk middleware for Redux

Thunk middleware for Redux. Contribute to reduxjs/redux-thunk development by creating an account on GitHub.

github.com