Mobx (1)
MobX는 프론트엔드를 위한 어플리케이션 상태 관리 라이브러리다.
주로 React와 함께 사용되며, 상태 관리 라이브러리라는 특성 때문에 종종 Redux와 비교됩니다.
한마디로 말해, MobX는 상태를 Observable하게 관리할 수 있도록 돕는 라이브러리 입니다.
wiki : Mobx
리덕스와 마찬가지로, MobX 는 리액트 종속적인 라이브러리가 아닙니다.
그냥 따로 쓸 수도 있습니다.
UI 프레임워크 / 라이브러리 없이 쓰셔도 되고, Vue, Angular 등이랑 써도 전혀 무방합니다.
1. Observable State (관찰 받고 있는 상태)
MobX를 사용하고 있는 앱의 상태는 Observable 합니다.
-> 관찰 받고 있는 상태. 우리의 앱에서 사용하고 있는 상태는, 변할 수 있으며, 만약에 특정 부분이 바뀌면, MobX 에서는 정확히 어떤 부분이 바뀌었는지 알 수 있습니다. (그값이, 원시적이 값이던, 객체이던, 배열 내부의 객체이던)
주요개념
import { observable } from 'mobx';
const calculator = observable({
a: 1,
b: 2
});
이렇게 Observable State 를 만들고나면 MobX 가 이 객체를 "관찰 할 수" 있어서 변화가 일어나면 바로 탐지해낼수있습니다.
Reactions 는 Computed Value 와 비슷한데요, Computed Value 의 경우는 우리가 특정 값을 연산해야 될 때 에만 처리가 되는 반면에, Reactions 은, 값이 바뀜에 따라 해야 할 일을 정하는 것을 의미합니다. 예를 들어서 Observable State 의 내부의 값이 바뀔 때, 우리가 console.log('ㅇㅇㅇ가 바뀌었어!') 라고 호출해 줄 수 있습니다.
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;
연산된 값은, 기존의 상태값과 다른 연산된 값에 기반하여 만들어질 수 있는 값입니다. 이는 주z로 성능 최적화를 위하여 많이 사용됩니다. 어떤 값을 연산해야 할 때, 연산에 기반되는 값이 바뀔때만 새로 연산하게 하고, 바뀌지 않았다면 그냥 기존의 값을 사용 할 수 있게 해줍니다.
const calculator = observable({
a: 1,
b: 2
});
reaction(
() => calculator.a,
(value, reaction) => {
console.log(`a 값이 ${value} 로 바뀌었네요!`);
}
);
reaction(
() => calculator.b,
value => {
console.log(`b 값이 ${value} 로 바뀌었네요!`);
}
);
const sum = computed(() => {
console.log('계산중이예요!');
return calculator.a + calculator.b;
});
sum.observe(() => calculator.a); // a 값을 주시
sum.observe(() => calculator.b); // b 값을 주시
calculator.a = 10;
calculator.b = 20;
console.log(sum.value);
console.log(sum.value);
calculator.a = 20;
console.log(sum.value);
sum.observe(() => calculator.a); // a 값을 주시
sum.observe(() => calculator.b); // b 값을 주시
autorun 은 reaction 이나 computed 의 observe 대신에 사용 될 수 있는데, autorun 으로 전달해주는 함수에서 사용되는 값이 있으면 자동으로 그 값을 주시하여 그 값이 바뀔 때 마다 함수가 주시되도록 해줍니다. 여기서 만약에 computed 로 만든 값의 .get() 함수를 호출해주면, 하나하나 observe 해주지 않아도 됩니다.
const calculator = observable({
a: 1,
b: 2
});
const sum = computed(() => {
console.log('계산중이예요!');
return calculator.a + calculator.b;
});
autorun(()=> console.log('a 값이 ${calculator.a} 로 바뀌었네요'));
autorun(()=> console.log('a 값이 ${calculator.b} 로 바뀌었네요'));
autorun(()=> sum.get());
calculator.a = 10;
calculator.b = 20;
console.log(sum.value);
console.log(sum.value);
calculator.a = 20;
console.log(sum.value);
Class 문법적용..
바로전에 구현 하였던 코드를 class 문법화 해보려고 한다.
import { observable, reaction, computed, autorun, decorate } from 'mobx';
class GS25{
basket = [];
get total(){
console.log('계산중입니다!.');
return this.basket.reduce((prev, curr) => prev + curr.price, 0);
}
select(name, price) {
this.basket.push({name, price});
}
}
decorate(GS25,{
basket: observable,
total : computed,
});
const gs25 = new GS25();
autorun(() => gs25.total);
gs25.select('물', 800);
console.log(gs25.total);
gs25.select('물', 800);
console.log(gs25.total);
gs25.select('포카칩', 1500);
console.log(gs25.total);
State관리 라이브러리 사용 목적
여러개의 Component 컴포넌트가 조합되에 페이지가 구성된다고 할때 Component간 상호작용 즉 데이터(State, Props)와 메소드의 접근이 까다롭게 됩니다.
SPA 개발이 없던 시절 서버렌더링 페이지에서 Jquery로 Dom을 조작하고 함수를 호출 할때는 Global Scope에서 대부분 이루어져서 크게 문제가 없었습니다. 그러나 기능 단위의 Component로 이루어진 최근의 SPA Framework에서는 부모자식의 관계로 Scope이루어져 있기 때문이 각 Component간 state와 method 접근이 복잡해 질수 있습니다. 이를 해결하기 위해서 State를 Global한 Store영역에서 관리하는 방법을 사용하여 state와 method의 접근이 용이 하게 됩니다.
State관리 라이브러리 사용 목적
여러개의 Component 컴포넌트가 조합되에 페이지가 구성된다고 할때 Component간 상호작용 즉 데이터(State, Props)와 메소드의 접근이 까다롭게 됩니다.
SPA 개발이 없던 시절 서버렌더링 페이지에서 Jquery로 Dom을 조작하고 함수를 호출 할때는 Global Scope에서 대부분 이루어져서 크게 문제가 없었습니다. 그러나 기능 단위의 Component로 이루어진 최근의 SPA Framework에서는 부모자식의 관계로 Scope이루어져 있기 때문이 각 Component간 state와 method 접근이 복잡해 질수 있습니다. 이를 해결하기 위해서 State를 Global한 Store영역에서 관리하는 방법을 사용하여 state와 method의 접근이 용이 하게 됩니다.