이번에 redux 와 recoil에 대해서 연구해볼 기회가 생겨서 간단하게 정리하고자 글을 쓴다. 개인적으로는 한번도 react도 쓴 적이 없기에 정말 기본적인 내용부터 알아야 했고, 나와 같은 사람들이 있고 react가 어떤건지 알고 싶은 사람들이 있다면 도움이 되고자 써본다.
React 에서는 컴포넌트(Component) 라는 요소가 있고, 이 요소는 두가지 속성값, props 와 state을 가지고 있는데 컴포넌트의 state에 따라서 페이지에 보여지는게 바뀌고, 컴포넌트이 소통할 때 props를 주고 받는다. 다만 React 에서 컴포넌트들의 관계는 단방향의 Tree 형태이기에, props는 부모에서 자식 컴포넌트로만 보낼 수가 있고, 자식들 간의 소통을 위해서는 자식의 상태를 부모로 올려줘서 부모 컴포넌트가 함수를 props에 넣어서 내려주는 식의 구조가 필요하다. 이럴 경우, 그 부모 아래에 있는 모든 컴포넌트들이 새롭게 Render이 되는데, 이것은 컴포넌트들이 각자 따로 반응해서 Render 된다는 리액트의 장점을 무효화 시키는 문제가 된다.
또한 컴포넌트들이 많아 지고 Tree 구조가 복잡해질수록 멀리 떨어진 자식 컴포넌트 사이의 소통을 props만을 이용해서 소통하기에는 지나치게 복잡하고 문제가 발생 시, 원인 파악도 힘들어진다. 이를 해결하기 위해서 props를 주고 받는 것 이외에 컴포넌트들의 상태를 관리하기 하는 방법이 필요하다.
아래 사진에서는 Redux 라는 상태관리 라이브러리를 사용하는걸 보여준다. Redux 가 없이 기본 리액트로 멀리 떨어진 컴포넌트들 끼리 소통하려면 굉장히 복잡하지만, Redux를 사용하면 효율적이고 간단한걸 볼 수 있다.
이미지 1. Redux의 유무에 따른 상태 변화의 차이
Redux는 기존 리액트에서 상태관리를 더욱 수월하게 하기 위해서 만들어진 라이브러리로, Store, Reducer, Action와 같은 요소들이 추가된다.
store.dispatch()
를 호출해야한다. store.dispatch()
가 호출되면, store은 reducer를 호출해서 state의 값들을 새롭게 변경한다.store.getState()
을 호출할 수 있다. const selectStateValue = state => state.value
const currentValue = selectStateValue(store.getState())
기존 리액트의 상태 관리가 어려운 이유 중 하나는 컴포넌트들이 단방향으로 소통하기 때문에 State의 공유가 어렵다는 점이었는데 Redux는 이러한 공유하는 State 들을 Tree 구조 바깥에 있는 Store 라는 곳에 모으는 방법으로 해결한다. 또한, 각각의 컴포넌트들이 Store에 Subscribe를 함으로써, Store 안에 있는 State가 바뀔 경우, 그 State을 구독하는 컴포넌트만 새롭게 Render하게 된다. 이로써 리액트의 장점이었던, 컴포넌트들이 따로 Render된다는 장점을 살릴 수 있게 해준다.
Recoil 또한 Redux와 마찬가지로 기존 리액트의 상태관리의 한계를 해결하기 위한 라이브러리로, Atom 과 Selector 두 개의 중요 요소들이 추가된다.
이미지 2. Recoil에서 쓰이는 Atom
const healthPointState = atom({
key: 'healthPoint',
default: 100,
});
useRecoilState
Hook을 이용해서 가져올 수 있다. 아래의 코드에서 버튼을 누르면, 텍스트에 표시된 숫자가 줄어들게 된다. function healthPointDisplay() {
const [healthPoint, setHealthPoint] = useRecoilState(healthPointState);
return (
<p> Remaining Health: {healthPoint} </p>
<button onClick={() => setHealthPoint((healthPoint) => healthPoint - 1)}>
Click to Decrease
</button>
);
}
const healthPointText selector({
key: 'healthPointText',
get: ({get}) => {
const healthPointValue = get(healthPointState);
const unit = 'pt';
return `${healthPointValue}${unit}`;
}
})
이상 글을 마무리 짓는데, 나도 생소한 주제이고 나름 정리해 놓은 글이기에 잘못된 점이 있다면 댓글에 지적해주면 감사할 것 같다