July 31st 2019
Contents
MobX
Computed property는 엄밀히 따지면 ES5에 포함된 문법입니다. 하지만 ES6의 Computed property를 사용하면 좀 더 간편하게 사용할 수 있습니다.
// 일반적인 class와 method
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const person = new Person('Grace', 'Hopper');
person.firstName; // 'Grace'
person.lastName; // 'Hopper'
person.fullName(); // 'Grace Hopper'
Computed property를 사용하면 아래 예시의 Person class의 consumer가 instance의 interface에 신경쓰지 않고 사용할 수 있습니다. 일관된 interface가 그렇지 않은 경우보다 일반적으로 더 나은 경우가 많다고 합니다.
// ES6
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
const person = new Person('Grace', 'Hopper');
person.firstName; // 'Grace'
person.lastName; // 'Hopper';
person.fullName; // 'Grace Hopper'
ES5에서도 computed를 사용할 수 있지만, 아래와 같이 깔끔한 모습이 아니기 때문에 아마도 많이 보지는 못 했을 것입니다.
// ES5
function Person(firstName, lastName) {
this.fistName = firstName;
this.lastName = lastName;
}
Object.defineProperty(Person.prototype, 'fullName', {
get: function() {
return this.firstName + ' ' + this.lastName;
}
});
Decorator는 기본적으로 higher-order function의 기능을 하지만, syntactic sugar를 제공합니다. 우선 앞서 사용했던 defineProperty를 다시 살펴보겠습니다. defineProperty에 인자로 타켓 객체, key 그리고 descriptor를 전달합니다.
만약 decorator를 직접 만들고자 한다면 아래와 같이 함수로 작성할 수 있습니다.
function decoratorName(target, key, descriptor) {
//...
}
예시로 readonly란 함수를 만들어 볼 수 있습니다.
function readonly(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
그리고 이것을 아래와 같이 decorator로 사용할 수 있습니다. 프로그래밍을 할 때는 'core-decorators'나 'lodash-decorator'등 라이브러리가 많기 때문에 실제로 구현을 해서 사용하는 경우는 드물 것입니다.
class Person {
constructor(firstName, lastName) {
this.fistName = fistName;
this.lastName = lastName;
}
@readonly get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
MobX의 주요 개념은 상태를 단순한 data structure에 담아두고, MobX에게 상태의 갱신을 위임한다는 것입니다. 기본 개념에 대한 다른 포스트도 있으니 참고해주세요.
우선 MobX를 이용해서 Person class를 아래와 같이 만들 수 있습니다.
const { computed, action, observable, autorun } = mobx;
class Person {
@observable firstName;
@observable lastName;
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@computed get fullName() {
return this.firstName + ' ' + this.lastName;
}
}
const person = new Person('Eric', 'Kim');
const quote = observable('Only Javascript can prevent forest fires.');
const render = () => {
document.body.innerText = person.fullName + ' : ' + quote;
};
autorun(render);
observable decorator를 사용해 우리는 해당 값이 변경되면 MobX를 통해 변경된 사실을 인지할 수 있습니다. 맨 밑의 autorun은 MobX가 관찰하고 있는 상태가 변경될 때마다 호출이 됩니다. 공식 문서 상 autorun은 함수를 자동으로 호출해야 하지만, 새로운 값을 반환하지 않는 함수에 적용하는것이 좋다고 소개합니다. 새로운 값을 생성해야 한다면, computed를 사용할 수 있습니다.