Mobx 처음 시작해보기(1)

Jo Seung Hyun
Oct 23, 2018 · 9 min read

리액트로 프로젝트를 진행하게 되면, state와 props 만으로는 데이터의 관리가 매우 어렵다는 것을 느끼게 된다. 대표적인 어려움으로는 밑의 그림과 같은 상황을 둘 수 있다.

only react

최상단의 component에서 state를 두고, 하위 component에 props를 뿌리는 상황이다. component수 자체가 적다면 큰 문제가 없을 수 있다. 하지만 그 수가 많아지고 관리해야하는 state와 props의 수가 많아진다면, 나중에 가서는 매우 혼란스러워 질 것이다. 이런 상황에서 다른 사람과 같이 프로젝트를 진행하게 된다면? 더 큰 어려움이 있을 수 있다.

물론, 이러한 상태 관리는 리액트 만으로도 할 수 있다. 리액트는 Cotext API 라는 것을 통해 다른 라이브러리 없이도 전역 상태를 관리할 수 있다. 이미 전 블로그에서 언급한 Redux를 포함한 mobx같은 라이브러리를 사용할 지, 사용안할 것인지는 유저의 선택에 따르면 된다. 각각 장단점이 있기 때문에 이번 블로그에서는 어느 것이 옳다, 그르다를 말하지는 않겠다.

리액트의 Context API, redux, 혹은 mobx을 사용하게 되면 위에 있는 복잡한 state의 관리는 다음과 같은 그림처럼 간편하게 변경될 수 있다.

with library

하나 혹은 다수의 store(저장소)를 두고 그곳에서 state를 저장해 둔다. 이제 props를 전달할 때 등 데이터의 이동의 절차가 매우 줄어들게 된다.

만약 Redux, Mobx 둘 중 어느 라이브러리를 선택할지 고민이라면, 둘 다 훌륭한 library이기 때문에 어느 것을 선택하든 좋은 결과를 가질 수 있을거라 말하고 싶다. 최근에는 GraphQl, Apollo까지 포함한 좋은 상태 관리 라이브러리가 많기 때문에 어느 것을 선택하여 공부하든 좋은 결과를 가져올 것이다. 하지만, 특별히 회사에서 사용하지 않거나 라이브러리의 장단점을 모두 보았는데도 굳이 하나만 선택하여 공부하고 싶다면 다음의 사진이 참고가 되길 바란다.

redux vs flux vs mobx

Mobx란

앞서 언급했다시피 React를 위한 상태 관리 라이브러리이다. 먼저 mobx의 상태 관리 flow를 사진으로 보자.

mobx data flow

redux의 dispatch, action의 개념에 익숙한 유저라면 약간 생소할 수 있다. 각각의 상태를 좀 더 자세히 살펴보자.

  1. state : 어플리케이션의 데이터 상태이다. 개념적으로 mobx는 spreadsheet와 유사하다고 한다. objects, arrays, primitives, references의 그래프의 형태로 어플리케이션을 구성하게 된다. 이것들은 spreadsheet의 data cells이 될 것이다.
  2. derivations : 파생값이라고 한다. 어플리케이션으로부터 자동으로 계산되는 모든 값을 뜻하게 된다. 이 값들은 간단한 값에서부터 복잡한 시각적 html 표현까지 다양한 값이 될 수 있다. spreadsheet의 개념과 비교하자면 차트를 들 수 있다.
  3. Reaction : reaction은 derivations와 유사한 개념이다. 가장 큰 차이점은 값을 생성하지 않는 함수라는 것이다. 대신 자동으로 특정 작업들을 수행시켜 주고, 이는 대체로 I/O(input, output)과 연관된 작업들이다. reaction은 적당할 때에 자동으로 DOM을 업데이트 하게 해주고 네트워크 요청을 하도록 해준다.
  4. Action : action은 state를 변경하는 모든 것을 말한다. 이 action들은 모두 동기적으로 처리된다.

위에 개념들은 redux를 사용했던 사람들이나 spreadsheet를 모르는 사람(본인 포함)이 처음 보았을 때 굉장히 생소한 개념들 일 수 있다. 때문에 실제로 react와 mobx를 이용한 간단한 프로젝트를 진행하면서 mobx의 개념과 기능들을 간단하게 살펴보도록 하자.

CREATE-REACT-APP 사용하기

mobx와 react를 이용한 간단한 로그인 화면을 구성해보면서 mobx를 익혀보도록 하자. 먼저 프로젝트 진행에 필요한 create-react-app 을 설치한 뒤 프로젝트를 생성해 보도록 하자. 진행할 때에는 기본적으로 yarn을 사용하도록 하겠다.

yarn global add create-react-app
create-react-app mobx_login

create-react-app(CRA)은 react로 프로젝트를 진행하는데 많은 도움을 주지만, 안타깝게도 CRA는 mobx 프로젝트를 진행하는데 필요한 decorator 문법을 default로 지원하지 않는다. decorator는 mobx를 사용하게 되면 보게 될 문법으로, @observable, @observer처럼 ‘@’를 사용한 문법의 형태를 가진다.

이를 사용하기 위해서는 두가지 방법이 있다.

1. yarn run eject
2. react-app-rewired

실제 프로젝트 진행은 yarn run eject를 사용하여 진행하도록 하겠다. 간단하게 설명하면 react-app-rewired는 eject를 하지 않고 cra를 customize할 수 있는 방법이다. 차후 기회가 된다면 react-app-rewired에 대해 따로 블로그를 작성하도록 하겠다.

yarn run eject

먼저 우리 프로젝트의 모든 설정과 스크립트를 customize해주는 방법이다. 주의할 점은, eject이후에는 eject이전으로 프로젝트를 되돌릴 수 없다는 점이다. cra에서 제공하지 않는 기능을 유저가 임의대로 설정할 때 많이 사용하는 방법이다. eject이후의 프로젝트의 폴더 구조를 살펴보자.

yarn run eject

이제 cra에서 default된 설정을 유저 임의대로 customize할 수 있게 되었다.

yarn add babel-preset-mobx

mobx에서 제공하는 preset인 bable-preset-mobx를 설치하면 이제 cra에서도 mobx의 decorator를 사용할 수 있게 된다. package.json 파일을 연 뒤 babel 부분을 다음과 같이 수정해준다.

"babel": {"presets": ["react-app","mobx"]}

이제 mobx를 사용할 준비가 완료되었다.

mobx 설치하기

mobx를 실제로 설치해보자.

yarn add mobx mobx-react

Mobx 사용해보기

이제 필요한 라이브러리와 설정을 완료하였으니 실제로 로그인 폼을 만들어가면서 mobx에 대하여 공부해보도록 하자. src 폴더의 App.js 파일을 다음과 같이 수정하여 yarn start 해보자.

App.js
login form

기존에 react만으로 input의 value를 조작했을 때 우리는 state와 setState를 사용했었다.

state = {
  email: '',
  password: ''}

mobx를 사용할 때에는 ‘observable’를 사용하여 state를 관리해주면 된다. 우리는 먼저 mobx와 mobx-react에서 observable과 observer를 import해야 한다.

import { observable } from 'mobx'import { observer } from 'mobx-react'

이제 observable과 observer를 통해 코드를 작성해보도록 하자.

App.js
6 line : observer는 앞으로 거의 모든 컴포넌트에 사용하게 될 것이다. observer는 mobx.autorun라는 함수를 가지고 컴포넌트의 render함수를 감싸게 되면서, observable한 데이터가 변경될 때마다 observer가 선언된 컴포넌트는 재 렌더링하게 해준다.모든 컴포넌트에서 observer를 사용하는것이 어플리케이션의 속도를 늦춘다고 걱정할 수도 있지만, mobx에서 이를 최적화하기 때문에 걱정할 필요는 없다. 가급적 모든 컴포넌트에 observer를 사용하는 것이 좋다.8, 9 line : mobx를 사용하게 되면 더이상 setState를 사용하지 않고 observable한 데이터를 직접 조작할 수 있게 된다. setState는 비동기적(asynchronous)으로 처리되기 때문에 가끔 react로만 프로젝트를 진행하다 보면 데이터가 변경되었는데도 렌더링이 즉각적으로 반영되지 않아 곤란할 때가 있었을 것이다. 변수에 observable선언만 해주면 이를 해결해줄 수 있고, 좀 더 사용이 간편하다.

setState와 observable의 차이점을 더 알고 싶다면 아래 링크를 참조하기 바란다.

이제 해당 input을 조작해주는 이벤트를 만들어 보자.

App.js
37 line : onChange라는 이벤트를 생성하여 input값을 handle하고 있다. 혹시 mobx의 상태 관리 중 action을 기억하는가? mobx에서 데이터를 조작할 때는 action decorator를 선언하여야 한다. 이 때, 37번째 줄에서 action.bound를 하는데, 이는 기본 react의 함수 bind와 같은 역할을 한다. constructor안에서 bind해도 작동하나 이번에는 설명의 목적으로 action.bound를 사용하였다.17 line : mobx의 observable한 값들은 이처럼 this를 이용해 사용한다.42 line : submit 버튼을 누르면 우리가 조작한 mobx 데이터의 출력값을 console로 확인할 수 있다.

다음 블로그에서는 mobx의 store 개념에 대해 설명하도록 하겠다.

Mobx 처음 시작해보기(2)

Jo Seung Hyun

Written by

Front-End Web Developer.