티스토리 뷰

Mobx state tree에 대해 사용해보고 간단한 카운터 예제를 만들어 보았다.

입문용이니 심오한 표현은 최대한 피하고 쉽게 이해할 수 있도록 구성하였다.

카운터 예제에 대한 스택은 React, Mobx, Mobx-state-tree, Mobx-react-lite가 사용되었다.

 

mobx state tree는 무엇인가?

상태를 관리하는 엔진이며 구조와 툴을 제공한다. 라고 공식문서에 적혀있다. 상태를 관리하는 라이브러리라고 생각하면 적절한 것 같다.

 

왜 mobx state tree를 사용해야 하는가?

상태관리로 mobx도 좋지만 mobx state tree는 프로젝트 구조가 좀 더 확장될 것에 대비하여 사용된다. 물론 소규모 프로젝트에도 사용가능하다. 

그 외에도 10가지 이유가 공식문서에 적혀있다.

궁금하신분은 읽어 보시길(https://mobx-state-tree.js.org/intro/welcome)

사용 방법은 어떻게 되는가?

본격적으로 사용법에 대해서 알아보자

가장 중요한 키워드는 세가지로 생각된다. model, actions, views.

 

model은 말그대로 데이터에 해당한다고 보면 된다.

actions는 데이터즉 state를 control하는 부분으로 생각되며, views의 경우 Computed properties를 나타내면 된다. 예를 들어 카운터에서는 표시되는 숫자라고 보면 된다. 계속해서 추적되며 따로 state값을 변경하지 않는다.

 

본격적으로 카운터 예제를 만들어 보자.

시나리오는 아래와 같다.

prop으로 넘겨주지 않아도 state값을 전역에서 가져오기 위해 Provider 컴포넌트를 만든다.

증가, 감소 버튼 컴포넌트를 만든다.

숫자를 보여주는 컴포넌트를 만든다.

store를 만든다.

 

최종 화면은 다음과 같다. 



폴더구조

먼저 전역에서 store를 가져올 수 있도록 Provider를 만들어보자. 참고로 mobx-react에서는 Provider를 제공한다.

하지만 mobx-react-lite에서는 React Api인 createContext, useContext를 활용하여 Provider를 구성할 수 있다.

 

store/Provider.js

import { createContext, useContext } from "react";

const StoreContext = createContext(null);

export const Provider = ({ value, children }) => {
  return (
    <StoreContext.Provider value={value}>{children}</StoreContext.Provider>
  );
};

export const useStore = () => {
  const store = useContext(StoreContext);
  return store;
};

createContext를 통해 새로운 context객체를 생성한다. 이것은 컴포넌트를 렌더할때 이 context 객체를 구독한다. 구독하므로써 context 값을 읽을 수 있다. 위에서 default value로는 null을 넣어줬다.

 

useStore은 store의 값을 가져오기 위해 만들었다. 코드를 보면 useContext를 통해 store의 값을 가져오고 반환한다.

 

store/CountStore.js

import { types } from "mobx-state-tree";

const CountStore = types
  .model({
    number: types.optional(types.number, 0)
  })
  .actions((self) => ({
    increase() {
      self.number += 1;
    },
    decrease() {
      self.number -= 1;
    }
  }));

export default CountStore;

types를 활용하여 model, actions 매소드를 사용할 수 있다.

위에서 말했듯이 model은 state 데이터 창고라고 생각하면 되고, actions는 state를 조정할 수 있다.

 

model에서 number라는 속성을 주었고 타입은 number이며 초기값을 0으로 해주었다.

actions에서 increase는 number를 1 증가 시키는 함수, decrease는 number를 1 감소시키는 함수이다.

 

store/index.js

import { types } from "mobx-state-tree";

import CountStore from "./CountStore";

const RootStore = types
  .model({
    CountNumber: types.optional(CountStore, {})
  })
  .views((self) => ({
    get showNumber() {
      return self.CountNumber.number;
    }
  }));

export default RootStore;

해당 예제에서는 규모가 커질 것에 대비하여 store를 하나로 모으기위해 RootStore를 구성해 주었다.

views에서는 CounterStore의 number를 반환한다. 아까 언급한 computed properties에 해당한다.

 

src/index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

import { Provider } from "../store/Provider";
import RootStore from "../store";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

const store = RootStore.create({
  CountNumber: { number: 0 }
});

root.render(
  <StrictMode>
    <Provider value={store}>
      <App />
    </Provider>
  </StrictMode>
);

 

App컴포넌트를 이전에 만든 Provider내부로 넣어주었다. value로는 store을 넣어주었는데 Rootstore을 store값으로 할당했다.

 

App.js와 자식 component를 한번에 보자

src/App.js

import "./styles.css";
import React from "react";
import CountScreen from "./CountScreen";
import ControlButton from "./ControlButton";

export default function App() {
  console.log("rendering App");

  return (
    <div className="App">
      <CountScreen />
      <ControlButton />
    </div>
  );
}

src/ControlButton.js

import React from "react";
import { useStore } from "../store/Provider";

const ControlButton = () => {
  console.log("rendering ControlButton");

  const store = useStore();

  return (
    <div>
      <button onClick={store.CountNumber.increase}>+</button>
      <button onClick={store.CountNumber.decrease}>-</button>
    </div>
  );
};

export default ControlButton;

src/CountScreen.js

import React from "react";
import { observer } from "mobx-react-lite";
import { useStore } from "../store/Provider";

const CountScreen = () => {
  console.log("rendering CountScreen");

  const store = useStore();

  return <div>{store.showNumber}</div>;
};

export default observer(CountScreen);

CountScreen은 observer로 감싸주었다. 이유는 버튼이 눌러짐에 의해 number값이 계속 바뀌기 때문에 추적하기 위해 감싸주었다.

 

카운터 예제 코드는 아래 URL에서도 확인 가능하다.

https://codesandbox.io/s/mobxstatetreepr-y5p6iv

 

mobxStateTreePr - CodeSandbox

mobxStateTreePr by Kyeong1024 using mobx, mobx-react-lite, mobx-state-tree, react, react-dom, react-scripts

codesandbox.io

 

아직 필자도 mobx state tree를 접한지 얼마되지 않아 불완전할 수 있다.

피드백은 언제나 환영이다. 🙏

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함