[TIL] Redux 1. 순수 JS에서 Redux와 상태관리 wtih. store와 reducer

2022. 10. 11. 23:29React/Redux

이 시리즈는 노마드 코더님의 "초보자를 위한 리덕스 101"을 보고 배운 내용을 정리합니다.

비약이나 틀린 내용이 있다면 언제든 댓글로 알려주세요..! (매우 환영입니다😀)

 

[시작하기 전에]

이번 1편은 React가 아니라 순수 JavaScript 환경에서 실습을 해봅니다.

이후에 React-Redux도 다루니 다른 편을 참고해주세요!


🎛️ Redux: JS에서 쓰는 상태관리 컨테이너

Redux는 그냥 저냥 듣기로는 React에서 쓸 수 있는 공용 저장소고, Props drilling같은 상태관리를 도와준다고 알고 있었다.

React 뿐 만 아니라 JavaScript 전반적으로 쓸 수 있는 "상태 관리"  컨테이너라고 한다.

 

구글링으로 상태관리 관련된 포스트를 보면 블로거 분들이 각자 상태관리를 자신만의 내용으로 정의하셨다.

내가 느낀 상태(state)"동적으로 관리되는 모든 데이터"이다. JS라는 언어 특성 상 동적으로 관리되는 변수를 기반으로 화면을 그릴 때 notify 문제 등과 같은 side effect 때문에 각각 정의하는 상태가 다른 것 같다.

 

Redux 공식문서는 "actions"라고 불리는 이벤트로 애플리케이션의 상태(state)를 관리하고 업데이트할 수 있는 라이브러리라고 정의한다. 일단 이번 1편에서는 redux를 구성하는 store, reducer, action의 세 가지 요소에 대해서 살펴보려고 한다.

 

1. Store, Reducer, Action의 정의


이 모델을 MY_CUSTOM_COUNTER 라고 하자.

 

store | state를 담아둘 수 있는 컨테이너.
reducer | state와 action으로 state를 업데이트를 도와주는 콜백함수.
action | reducer의 동작 제어를 도와주는 파라미터.

 

되게 직관적인 그림으로 그려봤는데,

단순하게 redux의 구조를 설명하면 store에 a(가칭) 변수를 만들어놓고, 모든 조작은 reducer에서 하는 구조다.

그런데 오직 store의 조작은 reducer에서 해줘야한다는 거다. 거기서 자연스럽게 파라미터(action)가 필요해진다.

 

써있는 것 처럼, UP, DOWN, JONNAUP, JONNADOWN의 네 가지 동작을 약속하고 나면 거기에 맞는 기능을 switch를 통해 구현해줘야한다.

 

자 이 구조를 한 번 코드로 보자.

 

2. MY_CUSTOM_COUNTER의 정의부 with Redux

[⚠️CAUTION]

createStore가 2022년 4월 최신 업데이트에서 deprecated되었습니다.

대신 legacy_createStore를 사용해야합니다.

import { legacy_createStore } from "redux";

const UP = 0;
const DOWN = 1;
const JONNAUP = 2;
const JONNADOWN = 3;

const MyCustomCounter = legacy_createStore(reducer);

const reducer = (state = 0, action) => {
  switch(action.type) {
    case UP:
      return ++count;
    case DOWN:
      return --count;
    case JONNAUP:
      return count + 10;
    case JONNADOWN:
      return count - 10;
    default:
      return count;
  }
}

 

store의 생성은 legacy_createStore함수를 이용해주면 되겠다. reducer는 별다를 것 없는 콜백 함수로 구현해주면 된다.

 

정의에 대한 구현이 끝났으니 이제는 실행을 해보..기 전에

Store interface에 있는 함수들을 한 번 소개하고 가면 좋을 것 같다.

 

2-1. Store interface의 함수들

/**
*@dispatch: action을 실행. state를 바꾸기 위한 유일한 방법.
*@getState: 지금 저장하고있는 state를 반환.
*@subscribe: state change listener.
*@replaceReducer: reducer 변경 콜백 함수.
*/
export interface Store<S = any, A extends Action = AnyAction> {
  dispatch: Dispatch<A>;
  getState(): S;
  subscribe(listener: () => void): Unsubscribe;
  replaceReducer(nextReducer: Reducer<S, A>): void;
}

 

dispatch로 reducer를 실행시켜주면 된다.

그리고 HTML에 noti를 주고 리로딩을 시켜주기 위해 subscribe 함수에는 DOM을 조작해주는 기능을 보통 넣는다.

 

3. MY_CUSTOM_COUNTER의 최종 구현 with Reduce

index.js

import { legacy_createStore } from "redux";

const plus = document.getElementById("add");
const minus = document.getElementById("minus");
const jonnaPlus = document.getElementById("jonna-add");
const jonnaMinus = document.getElementById("jonna-minus");
const number = document.querySelector("span");

const UP = 0;
const DOWN = 1;
const JONNAUP = 2;
const JONNADOWN = 3;

const MyCustomCounter = legacy_createStore(reducer);

const reducer = (state = 0, action) => {
  switch(action.type) {
    case UP:
      return ++count;
    case DOWN:
      return --count;
    case JONNAUP:
      return count + 10;
    case JONNADOWN:
      return count - 10;
    default:
      return count;
  }
}

const onChange = () => {
  number.innerText = MyCustomCounter.getState();
}

MyCustomCounter.subscribe(onChange);
plus.addEventListener("click", () => countStore.dispatch({ type: UP }));
minus.addEventListener("click", () => countStore.dispatch({ type: DOWN }));
jonnaPlus.addEventListener("click", () => countStore.dispatch({ type: JONNAUP }));
jonnaMinus.addEventListener("click", () => countStore.dispatch({ type: JONNADOWN }));

 

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>Vanilla Redux</title>
    </head>
    <body>
        <button id="jonna-add">Add</button>
        <button id="add">Add</button>
        <span>0</span>
        <button id="minus">Minus</button>
        <button id="jonna-minus">Add</button>
    </body>
</html>

 

이런 식으로 사용한다.

다음에는 TO-DO 리스트로 조금 더 심화된 예제와 함께 돌아보는 걸로..!

'React > Redux' 카테고리의 다른 글

[TIL] Redux3. React-Redux 사용법.  (0) 2022.10.18
[TIL] Redux 2. Never do mutate the state.  (0) 2022.10.13