09. 사용 사례 시나리오 3: Valtio
proxy를 사용한 변경 감지와 불변 상태 생성, 리렌더링 최적화
🔖 1. Valtio란?
특장점
Proxy를 사용하여 상태를 추적하고, 상태 변경 시 관련 컴포넌트만 자동으로 업데이트 해주는 방식
즉, 상태 객체를 직접 다루듯이 편하게 수정하면, Valtio가 그 변화를 감지하고 필요한 부분만 리렌더링해 준다.
상태 객체를 Proxy로 감싸 상태에 대한 모든 접근을 감지한다. 어떤 컴포넌트가 상태의 어느 부분을 읽었는지 파악하고, 그 부분이 변할 때만 그 컴포넌트를 다시 렌더링한다.
useSnapshot
훅으로 현재 상태 스냅샷을 읽을 수 있으며, 상태 변경 시 자동으로 업데이트된 스냅샷을 받아볼 수 있다.상태를 기존 JS 객체 다루듯이 변경하면 되므로 러닝 커브가 낮다.
Proxy 기반이라 예측하기 힘든 시나리오에선 주의가 필요할 수 있다.
예시 코드
import { proxy, useSnapshot } from 'valtio';
// 1. 상태 정의: Proxy로 상태를 감싸는 proxy 함수를 사용
const state = proxy({
count: 0,
text: 'Hello',
});
// 2. 상태를 읽고 변경하는 컴포넌트
function Counter() {
// useSnapshot으로 현재 상태 스냅샷 얻기
const snap = useSnapshot(state);
return (
<div>
<p>Count: {snap.count}</p>
<button onClick={() => state.count++}>+1</button>
</div>
);
}
function TextDisplay() {
const snap = useSnapshot(state);
return (
<div>
<p>Text: {snap.text}</p>
<button onClick={() => (state.text = state.text + '!')}>Add "!"</button>
</div>
);
}
export default function App() {
return (
<div>
<h1>Valtio Example</h1>
<Counter />
<TextDisplay />
</div>
);
}
🔖 2. 언제 Valtio를 사용하면 좋을까?
언제 Valtio를 사용하면 좋을까?
전역 상태를 쉽게 정의하고 갱신하고 싶을 때
상태 변경을
state.count++
와 같이 직관적으로 하고 싶을 때
언제 Valtio를 사용하지 않는 것이 좋을까?
대규모 프로젝트에서 엄격한 패턴이 필요할 때(이럴 때는 Redux의 action, reducer 처럼 일관된 패턴을 쓰는 것이 좋을듯)
Redux의 MobX처럼 복잡한 디버깅이나 추적 기능이 필요한 경우, Valtio의 Proxy 기반 렌더링 최적화가 단점이 될 수 있다.
타입 안정성이 필요할 때는 Valtio의 느슨한 구조가 단점이 될 수 있다.
Last updated