예전에 proxy-compare라는 녀석과 context api를 활용해서 간단한 상태관리 툴을 만들었었는데, 내가 만들고 싶었던 궁극체(?)느낌의 프로젝트가 이미 존재했다. 바로 valtio라는 녀석이다.

이 글은 아주 짧게 valtio의 장점과 동작원리만 간단하게 소개하고싶다. 그래야 다른 사람들도 많이 쓸 것 같다

Valtio, makes proxy-state simple for React and Vanilla

valtio는 zustand를 만든 Poimandres 오픈소스 그룹에서 만든 상태관리 라이브러리이다. 리액트 생태계에 있는 대부분의 상태관리 툴은 이쪽에서 만든다고 봐도 무방하다.

Valtio의 장점

랜더링 최적화 자동화

이것만으로도 valtio를 쓸만하다.

const counterStore = proxy({ count: 0, text: "hello" });

const Counter: React.FC<CounterProps> = () => {
  const { count } = useSnapshot(counterStore);

  return (
    <View>
      <Text>Counter: {count}</Text>
    </View>
  );
};

이렇게 구성된 컴포넌트라고 가정했을때, 참조를 count에 대해서만 하고 있기 때문에 그 외의 값이 바뀌어도 리랜더링이 일어나지 않는다. 다시말해 text에 어떤 값이 들어와도 리랜더되지 않는다. 그냥 이런식으로 스토어를 만들고 사용처에서는 참조하는 값만 신경써주면 자동적으로 랜더링이 최적화된다.

불변성 신경쓸 필요 없음

const counterStore = proxy({ count: 0, text: "hello" });

const Counter: React.FC<CounterProps> = () => {
  const { count } = useSnapshot(counterStore);

  return (
    <View>
      <Text>Counter: {count}</Text>
      <Button title="increase" onPress={() => {
	      counterStore.count++;
      }}/>
    </View>
  );
};

보통의 리액트라면 표시된 라인은 제대로 동작하지 않는다. 불변성을 해치기 때문이고 여러번 중첩된 복잡한 오브젝트의 경우 특정 벨류를 바꾸고자 할 때 불변성을 지켜주려면 상당한 노력이 드는데, 이를 immer로 해결하곤 했다. 그런데 valtio에서는 그냥 저렇게 사용하기만 하면 된다.

간결한 사용

굳이 예를 들자면 사용시에 recoil과 흡사하게 사용하면 된다.

  1. proxy 객체 생성
  2. useSnapshot으로 상태 구독