
React Hooks에서 useMemo와 useState를 사용하여 계산된 상수 정의하기
React Hooks를 사용할 때, 초기 props 또는 상태에서 유도되는 값이며 변경되지 않을 계산된 상수를 정의해야 할 때가 있습니다. 이러한 상황에서는 두 가지 옵션이 있습니다: useState 또는 useMemo를 사용하는 것입니다. 이들은 기능적으로 동등해 보일 수 있지만, 성능 및 기타 고려 사항에 따라 그 차이를 고려하는 것이 중요합니다.
useState 접근 방식
useState 훅을 사용하면 함수 컴포넌트의 재렌더링 동안 유지되는 상태 변수를 선언할 수 있습니다. useState를 사용하여 계산된 상수를 다음과 같이 정의할 수 있습니다:
const [calculatedConstant] = useState(calculateConstantFactory);
이 접근 방식은 상수를 상태 변수로 초기화합니다. 그러나 의미론적으로 말하면, 이는 useState의 올바른 사용법이 아닙니다. 상수 값이 업데이트되고 재렌더링되어야 하는 경우에 사용해야 하는데, 계산된 값은 그렇지 않기 때문입니다.
useMemo 접근 방식
useMemo 훅은 주로 성능 최적화를 위해 사용됩니다. 함수의 결과를 메모화하고 종속성이 변경될 때에만 다시 계산합니다. useMemo를 사용하여 계산된 상수를 다음과 같이 정의할 수 있습니다:
const calculatedConstant = useMemo(calculateConstantFactory, []);
useMemo를 사용하는 것은 상수 값을 정의하는 의도된 의미론적인 접근 방법이 아닙니다. 불필요한 다시 계산을 최소화하여 성능을 최적화하고자 할 때 사용해야 합니다. 그러나 지금은 의도한 대로 작동할 수 있지만, useMemo를 잘못 사용하면 미래에 예측할 수 없는 동작을 일으킬 수 있습니다.
대안적인 접근 방식
값이 컴포넌트의 첫 번째 렌더링에서 필요하지 않은 경우, useRef와 useEffect를 함께 사용해 볼 수 있습니다:
const calculatedConstant = useRef(null);
useEffect(() => {
calculatedConstant.current = calculateConstantFactory();
}, []);
이 접근 방식은 컴포넌트의 렌더링을 차단하지 않고 상수 값을 초기화할 수 있습니다. 그러나 이 방식의 문제는 초기화 후에도 값이 변경되어 컴포넌트에 반영되지 않는다는 것입니다.
값이 컴포넌트의 첫 번째 렌더링에서 사용되어야 하지만 렌더링이 차단되지 않길 원한다면, 이전 접근 방식을 수정해 볼 수 있습니다:
const calculatedConstant = useRef(null);
if (!calculatedConstant.current) {
calculatedConstant.current = calculateConstantFactory();
}
// calculatedConstant.current의 값을 사용합니다;
이 수정 방식은 값이 설정될 때까지 컴포넌트 렌더링을 차단하지 않습니다. 그러나 값을 초기화할 때까지 렌더링이 차단된다는 점을 주의해야 합니다.
컴포넌트를 다시 렌더링해야 하는 경우, useState와 useEffect를 조합하여 다음과 같이 사용할 수 있습니다:
const [calculated, setCalculated] = useState();
useEffect(() => {
setCalculated(calculateConstantFactory());
}, []);
// calculated의 값을 사용합니다
이 접근 방식은 값이 변경될 때마다 컴포넌트를 다시 렌더링할 수 있습니다.
결론
useMemo와 useState 모두 계산된 상수를 정의하는 데 사용될 수 있지만, 상수 값의 의도된 의미론적용과 요구 사항과 일치하는 접근 방식을 선택하는 것이 중요합니다. 의미론적으로 useState는 상수 값에 대한 올바른 선택이 아니며, useMemo를 잘못 사용하면 미래에 예측할 수 없는 동작을 일으킬 수 있습니다.
상수 값이 첫 번째 렌더링에서 필요하지 않은 경우 useRef와 useEffect를 함께 사용할 수 있습니다. 값이 첫 번째 렌더링에서 차단되지 않고 사용되어야 하는 경우, 수정된 useRef 접근 방식을 고려할 수 있습니다. 마지막으로, 컴포넌트가 상수 값에 기초하여 자체적으로 다시 렌더링되어야 하는 경우 useState와 useEffect를 결합하여 사용할 수 있습니다.