React를 쓰는 많은 분들이 프로젝트를 시작하기 전 첫 번째로 고민하게 되는 기술스택이 글로벌 상태관리 라이브러리 redux
와 mobx
중 어떤 것을 선택할까가 아닐까 합니다.
깃헙 스타수로 보면 리덕스의 인기가 좀 더 많은 것을 알 수 있습니다. 저도 리덕스를 주로 쓰지만 mobx
의 장점 중 하나는 데코레이터 문법과 computed value 에 있다고 생각합니다.
@computed get discountedPrice() {
return this.price * this.discount
}
이런식으로 store
에 데코레이터 문법으로 getter를 달아주는 방식입니다. redux
에는 api가 없지만 reselect
라는 라이브러리를 통해서 비슷한 방식을 구현할 수 있습니다.
이제 react
에 훅이 도입되면서 추가 라이브러리 없이도 computed value를 쉽게 구현할 수 있게 되었습니다.
스토어 fruitStore
에 서버로부터 과일의 할인율과 가격 데이터를 받아 저장되어 있다고 해보겠습니다.
const initialState: FruitStore = {
apple: { discount: 0.03, price: 1000 },
orange: { discount: 0.12, price: 3000 },
grape: { discount: 0.2, price: 8000 },
...
};
저장된 데이터는 Tag
컴포넌트에 3가지 방법으로 표현됩니다.
- 할인된 가격을 표현해줍니다.
- 할인이 적용된 최종 결제가격을 보여줍니다.
- 할인율을 읽기 쉽게 %로 보여줍니다.
데이터를 view에 표현하기 위해서는 항상 아래와 같이 값을 변환해주어야 합니다.
const discountedPrice: number = price * discount;
const billingPrice: number = price * (1 - discount);
const discountPercent: string = `${discount * 100} %`;
만약에 위의 데이터를 쓰는 컴포넌트가 여러개라면 각 컴포넌트마다 같은 코드를 복사/붙여넣기 해야 할 것이고 유지보수하기도 점점 어려워질 것입니다.
스토어에서 3가지 데이터를 모두 저장하는 것도 생각해볼 수 있습니다. 하지만 이런 경우에 nested 된 형태로 스토어를 관리해야 될 가능성이 높아지고, view의 형태가 다양해지면 복잡성이 기하급수적으로 커지게 됩니다.
커스텀훅과 useMemo
를 조합해 computed value를 구현해보겠습니다.
// custom hook
function useFruitTag(fruit: string) {
const { discount, price } = useSelect(({ fruitStore }) => fruitStore[fruit]);
const discountedPrice = useMemo(() => price * discount, [discount, price]);
const billingPrice = useMemo(() => price * (1 - discount), [discount, price]);
const discountPercent = useMemo(() => `${discount * 100} %`, [discount]);
return {
discountedPrice,
billingPrice,
discountPercent,
};
}
// component
function AppleTag() {
const { discountedPrice, billingPrice, discountPercent } = useFruitTag('apple');
return (
<div>
<h1>Apple</h1>
<p>{discountedPrice}</p>
<p>{billingPrice}</p>
<p>{discountPercent}</p>
</div>
);
}
이런 방식으로 reselect
나 @computed
없이도 computed value를 쉽게 만들어 쓸 수 있습니다. useMemo
를 이용해서 캐싱된 값을 쓰기도 쉽고, 과일의 종류가 늘어나거나 대응해야 하는 view가 늘어나더라도 쉽게 처리할 수 있습니다. 무엇보다 관심사별로 로직이 분리되면서 코드를 읽기 쉬워진다는 게 가장 큰 장점인 것 같습니다.
p.s
useMemo
가 reselect
를 완전히 대체한다는 뜻은 아닙니다. 관련된 내용은 여기 에 잘 설명되어 있습니다.
Top comments (0)