MobX는 Redux와 같은 인기있는 React 상태 관리 라이브러리이다.
MobX의 주요 개념들
1. Observable State( 관찰 받고 있는 상태 )
MobX를 사용하고 있는 앱의 상태는 Observable하다.
즉, 관찰 받고 있는 상태이다.
앱에서 사용하고 있는 State는 변할 수 있고, 만약 특정 부분이 바뀌면 MobX에서 어떤 부분이
바뀌었는지 알 수 있다.
2. Computed Value ( 연산된 값 )
연산된 값은 기존 상태값과 다른 연산된 값에 기반하여 만들어질 수 있는 값이다.
주로 성능 최적화를 위해서 사용된다. 어떤 값을 연산해야 할 때, 연산에 기반이 되는 값이 바뀔때만
새롭게 연산하고, 바뀌지 않으면 기존의 값을 사용할 수 있다.
예를들어, 800원짜리 물병을 4병 살때 total()이라는 함수를 사용한다고 생각하자.
그럼 함수를 통해서 계산한 결과로 3,200원을 알 수 있다.
이때 다시 4병이 얼마인지 확인할 때는 다시 계산할 필요 없이 3,200원이 나오게 되고 추가로 1병을
더 사게 된다면 다시 4,000원 인것을 계산합니다.
3. Reactions ( 반응 )
Reactions는 Computed Value와 비슷하다.
Computed Value는 특정 값을 연산할 때만 처리되는 반면, Reactions는 값이 바뀜에 따라 할일을 정하는 것을
의미한다.
예를 들어, Observable State의 내부 값이 바뀔 때, console.log(" 값 바뀜")을 호출할 수 있다.
4. Actions ( 행동 )
Actions은 상태에 변화를 일으키는 것을 말한다.
만약 Observable State에 변화를 일으키면 그것을 Actions 이라고 한다.
React 없이 MobX 사용하기
MobX는 리액트 종속 라이브러리가 아니다.
당연히 따로 쓸수 있으며, Vue, Angular 등과 같이 쓸수도 있다.
npm install mobx
MobX를 먼저 설치해주었다.
import { observable, reaction, computed, autorun } from "mobx";
MobX에서 자주 사용되는 몇가지 함수를 불어왔다.
observable
observable 함수는 Observable State를 만들어준다.
import { observable, reaction, computed, autorun } from "mobx";
const calculator = observable({
a: 1,
b: 2,
});
덧셈을 해주는 계산기 객체를 만들어봤다.
Observable State를 만들면 MobX가 이제부터 내부의 객체를 " 관찰 " 할 수 있어 변화가 일어나면 바로 확인할 수 있다.
reaction
특정 값이 바뀔 때 어떤 작업을 하고 싶다면 reaction 함수를 사용한다.
import { observable, reaction, computed, autorun } from "mobx";
// Observable State
const calculator = observable({
a: 1,
b: 2,
});
reaction(
() => calculator.a,
(value, reaction) => {
console.log(`a 값이 ${value}로 바뀌었다.`);
}
);
reaction(
() => calculator.b,
(value, reaction) => {
console.log(`b 값이 ${value}로 바뀌었다.`);
}
);
calculator.a = 10;
calculator.b = 20;
a와 b가 바뀔 때 console.log로 변화를 확인하는 코드를 작업했다.
실행한다면,
a 값이 10로 바뀌었다.
b 값이 20로 바뀌었다.
출력이 되는 것을 확인할 수 있다.
computed
computed 함수는 연산된 값을 사용해야 할 때 사용된다.
조회할 때 마다 특정 작업을 처리하는 것이 아닌, 의존하는 값이 바뀔 때 미리 값을 계산하고 조회할 때
캐싱된 데이터를 사용한다는 것이다.
import { observable, reaction, computed, autorun } from "mobx";
// Observable State
const calculator = observable({
a: 1,
b: 2,
});
// reaction
reaction(
() => calculator.a,
(value, reaction) => {
console.log(`a 값이 ${value}로 바뀌었다.`);
}
);
reaction(
() => calculator.b,
(value, reaction) => {
console.log(`b 값이 ${value}로 바뀌었다.`);
}
);
const sum = computed(() => {
console.log("계산중");
return calculator.a + calculator.b;
});
sum.observe_(() => calculator.a);
sum.observe_(() => calculator.b);
calculator.a = 10;
calculator.b = 20;
console.log(sum.get());
console.log(sum.get());
calculator.a = 30;
console.log(sum.get());
sum.observe_(() => calculator.a);
sum.observe_(() => calculator.b);
computed가 a값과 b값을 주시하고 있다가
calculator.a = 10;
calculator.b = 20;
a값 또는 b값이 변경되면 내부 함수를 호출한다.
즉, sum.get()을 통해서 함수가 호출되는 것이 아닌, observe_()를 통해 주시하고 있던 Observable State가 변경되면
자동으로 함수가 호출되어 결과 값을 캐싱하고 있다가 함수가 호출되면 결과 값만 return 한다.
autorun
autorun은 reaction이나 computed의 observe 대신 사용될 수 있다.
autorun으로 전달해주는 함수에서 사용되는 값이 있으면 자동으로 그 값을 주시하여 값이 바뀔때마다 함수가
주시되도록 해준다.
만약, computed 로 만든 값의 .get() 함수를 호출하면, 하나하나 observe_ 해주지 안아도 된다.
import { observable, reaction, computed, autorun } from "mobx";
// Observable State
const calculator = observable({
a: 1,
b: 2,
});
// computed
const sum = computed(() => {
console.log("계산중");
return calculator.a + calculator.b;
});
autorun(() => console.log(`a 값이 ${calculator.a}로 바뀌었습니다.`));
autorun(() => console.log(`b 값이 ${calculator.b}로 바뀌었습니다.`));
autorun(() => sum.get());
calculator.a = 10;
calculator.b = 20;
console.log(sum.get());
console.log(sum.get());
calculator.a = 30;
console.log(sum.get());
reaction을 없애고, observe_() 함수도 없앴는데 여전히 문제없이 콘솔이 찍히게 되었다.
class 문법을 사용하기
ES6의 class 문법을 사용하면 더 깔끔하게 코드를 작성할 수 있다.
class로 장바구니를 구현하고 MobX를 적용하겠다.
import { autorun } from "mobx";
class GS256 {
basket = [];
get total() {
console.log("계산 중");
return this.basket.reduce((prev, curr) => prev + curr.price, 0);
}
select(name, price) {
this.basket.push({ name, price });
}
}
const gs256 = new GS256();
autorun(() => gs256.total);
gs256.select("물", 800);
console.log(gs256.total);
gs256.select("물", 800);
console.log(gs256.total);
gs256.select("가나파이", 3800);
console.log(gs256.total);
decorator 문법 makeObservable
decorator 문법은 자바스크립트의 정규 문법은 아니지만, babel 플러그인을 통해서 사용 할 수 있는 문법이다.
하지만, 유감스럽게도 MobX v6으로 오면서 더이상 지원하지 않는다....
대신 makeObservable을 통해서 간단하게 사용할 수 있다.
import {
observable,
reaction,
computed,
action,
makeObservable,
autorun,
} from "mobx";
class GS256 {
basket = [];
constructor(value) {
makeObservable(this, {
basket: observable,
total: computed,
select: action,
});
}
get total() {
console.log("계산 중");
return this.basket.reduce((prev, curr) => prev + curr.price, 0);
}
info() {
console.log(basket);
}
select(name, price) {
this.basket.push({ name, price });
}
}
const gs256 = new GS256();
autorun(() => {
if (gs256.basket.length > 0) {
console.log(gs256.basket[0].name, gs256.basket[gs256.basket.length - 1]);
}
});
reaction(
() => gs256.basket.length,
(value, previousValue, reaction) => {
console.log(value, previousValue);
}
);
gs256.select("물", 800);
console.log(gs256.total);
gs256.select("물", 800);
console.log(gs256.total);
gs256.select("가나파이", 3800);
console.log(gs256.total);
깃허브
https://github.com/SeoJaeWan/mobx-without-react
'React > 이론' 카테고리의 다른 글
[React] MobX - 심화 (2) | 2022.05.05 |
---|---|
[React] MobX - React에서 사용하기 (3) | 2022.05.03 |
[React] import React from 'react'는 어디에 쓰일까? (1) | 2022.04.17 |
[React] Virtual DOM (2) | 2022.03.12 |
[React] 비동기 작업(콜백 함수, Promise, async, await) (0) | 2022.02.08 |