MobX의 기능 중 하나인 데코레이터(@)를 이용해서 적용하는 코드는 create-react-app 에서 공식적으로 지원하는 메서드가 아니에요.
그래서 이를 지원하게 하려면 babel 설정을 만져야 하는데, babel 설정을 만지려면 두가지 방법이 있습니다. 첫번째는 지독한 yarn eject
, 두번째는 customize-cra
와 react-app-rewired
패키지를 이용하는 방법이 있어요.
일단 첫번째로, 의존성 관리가 매우 매우 어렵다는 것입니다. yarn eject
를 하고 Dependency 를 설치하면, 다른 패키지와의 의존성을 신경써야 패키지들끼리 충돌이 나지 않아요.
두번째로, 저희가 원하는 순기능이기도 하고, 역기능이 될 수도 있는, babel, webpack 설정을 바꿀 수 있는 기능입니다. 이도 마찬가지로 굉장히 복잡하므로, 필요한 설정만 수정하는 것이 아니면 저 뿐만 아니라 여러분의 생산성을 떨어뜨릴 것이 분명하기 때문이지요.
customize-cra
와 react-app-rewired
패키지를 이용한다고 해도 create-react-app 에서 기본적으로 지원되던 모든 기능이 정상적으로 동작하지 않을 수 있습니다.
하지만 yarn eject
와는 다르게 되돌아갈 수 있으므로, 항상 그 부분을 염두에 두고 코드를 작성하세요.
앞서 말했듯, babel 설정을 만져줘야 하기 때문에, 해당 설정부터 먼저 만져주도록 해요.
React - eject 없이 Mobx 데코레이터 사용하기를 참고했어요.
[yarn]
yarn add --dev customize-cra react-app-rewired @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties core-decorators
[npm]
npm i --save -d customize-cra react-app-rewired @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties core-decorators
package.json에 있는 scripts 중, eject에 있는 것을 제외한 모든 react-scripts 를 react-app-rewired 로 교체해요. 따로 설정해 놓으신 스크립트가 있으셔도 react-scripts 만 교체하시면 됩니다.
...
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject",
...
}
...
기존에 다른 세팅이 있으셨던 분은 현재 작성된 코드와 적절히 병합하시면 됩니다!
...
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
]
]
}
...
const {
addDecoratorsLegacy,
disableEsLint, // eslint를 끄는 것이 아니에요 ^^
override,
} = require("customize-cra");
module.exports = {
webpack: override(
disableEsLint(),
addDecoratorsLegacy()
),
};
기존에 config 파일을 만들어두지 않으셨다면 프로젝트의 루트 디렉토리에 본인에게 맞는 config (Typescript 를 사용하고 계신다면 tsconfig.json, Javascript 를 사용하고 계신다면 jsconfig.json 이겠죠?) 를 생성하시면 됩니다.
{
"compilerOptions": {
...
"experimentalDecorators": true
...
},
...
}
그리고 위와 같이 experimentalDecorators 를 true 로 설정해주시면 lint 상에서 오류가 발생하지 않아요.
MobX는 애초에 React에서 사용하기 위해 제작되었기 때문에 React에 적용하기가 굉장히 간편해요. 모듈 몇 개만 설치하고, 적용하면 끝! 타입스크립트도 신경 쓸 필요가 없습니다!
[yarn]
yarn add mobx mobx-react
[npm]
npm i --save mobx --save mobx-react
/stores
폴더를 생성한 뒤, 당신만의 스토어 파일을 생성해요.저는 YourStore
로 해볼게요.
참, 저는 타입스크립트를 사용하였습니다만 자바스크립트의 경우에도 코드가 거의 동일합니다.
YourStore.ts
import { observable, action } from 'mobx';
export default class YourStore {
@observable yourStore = 'hello';
@action changeStoreValue = (value: string) => {
this.yourStore = value;
};
@action changeToWorld = () => {
this.yourStore = "World";
}
}
위에서 볼 것은 두가지 인데요.
첫번째로 @observable
입니다. 이는 React 의 state 와 비슷한 역할을 하는데요. MobX상에서 변수의 역할을 하신다고 보면 됩니다. 따라서 MobX에서 변수를 선언하실 때에는 일반적인 var
let
const
와 같은 키워드가 아닌, @observable
로 선언하셔야 합니다.
두번째로, @action
인데요. 이는 값을 변경해 줄 수 있는 메서드, 즉 React 에서의 setState
의 역할을 하신다고 보면 됩니다. 하지만 기존의 setState 와는 다르게 함수를 커스터마이징 할 수 있는데요. 예제코드처럼 changeToWorld를 호출하게 되면 yourStore 는 World 라는 값으로 바뀌게 됩니다. 이를 활용해서 여러분들만의 코드를 제작하실 수 있어요. 추후 에피소드에서 이와 관련된 Side-effects 에 관해서 다룰거에요.
import React from "react";
import ReactDOM from "react-dom";
...
import App from "./App";
import { Provider } from "mobx-react";
import YourStore from "./stores/YourStore";
const yourstore = new YourStore();
const RenderComponent = () => (
<Provider yourstore={yourstore}>
<App />
</Provider>
);
ReactDOM.render(<RenderComponent />, document.getElementById("root"));
import React from "react";
import { observer, inject } from "mobx-react";
@inject("yourstore")
@observer
export default class App extends React.Component<any> {
render() {
return (
<div>
<div>value = {this.props.yourstore.yourStore}</div>
<div>
<button onClick={this.props.yourstore.changeToWorld}>
Change to world
</button>
</div>
</div>
);
}
}
여기서 두 가지의 새로운 데코레이터 문법이 있는데요.
@inject
는 3번처럼 최상단 컴포넌트에서 Provider를 설정할 때 props로 준 store를 불러옵니다. 만약 Provider 에 props 로 a라는 props를 전달해 주었으면, @inject('a');
로 불러와야 합니다. inject 를 하게 되면 a라는 props가 전달이 되며, a 안의 observable value 나 action을 불러와서 사용할 수 있습니다.
@observer
는 해당 클래스를 watch (감시) 하여 값이 바뀌게 되면 this.forceUpdate() 를 트리거 해주겠다는 것입니다.
이제 MobX 를 통해 여러분의 코드를 훨씬 생산적으로 제작할 수 있습니다. 즐코딩!
감사합니다 ㅎㅎ 덕분에 깔끔하게 설치했네요!