코드 리뷰하기

About React, useEffect
2023/11/02

정답

문제의 코드는 이렇게 정리하는 것이 이해하기도, 성능적으로도 좋습니다.

const Component = ({ items }) => {
  const [filter, setFilter] = useState(state.default);
  const filteredItems = items.filter(({ state }) => state === filter);
  ...
};

useEffect없이도 필터링 된 배열을 만들 수 있습니다.

무슨 차이가 있을까요?

문제점

useEffect

useEffect는 읽고 이해하기 쉽지 않습니다. 문제의 경우 단순하지만 컴포넌트가 복잡해질수록 코드를 변경할 때 신경 쓸 부분이 많아집니다.

상태 변경에 대응해 어떤 로직을 실행해야 할 경우, 무의식적으로 useEffect를 사용하는 것은 많은 리액트 개발자가 저지르는 실수입니다.

해당 로직이 외부 시스템과 함께 수행되어야 하는 side effect가 맞는지 고민해봐야 합니다.

일반적으로 비동기 데이터를 요청하거나, 브라우저 API를 이용하거나, 타이머 함수 사용 등이 이에 해당합니다.

위의 경우 그렇지 않죠.

컴포넌트를 이해하기 어렵게 만들 뿐 아니라, filteredItems라는 상태를 도입해 불필요한 추가 렌더링을 발생시킵니다.

불필요한 상태

수정한 코드는 filteredItems를 상태로 두지 않았습니다.

filteredItems 상태를 두는 것은 추가 렌더링 외에도 데이터 동기화 문제가 있습니다.

items의 데이터를 복사한 새 배열을 상태로 저장하고 있어서 items가 업데이트 되어도 filteredItems에 복사한 낡은 데이터를 가지고 있게 됩니다.

이는 특히 filteredItems의 요소를 이용해 특정 작업을 수행하려고 할 경우 찾기 어려운 버그를 만들 가능성이 있습니다.

수정한 방식은 items의 변경에 따라 새로운 filteredItems 배열을 만들어 동기화를 따로 할 필요가 없습니다.

이처럼 useEffect를 사용할 때에는 정말 필요한 부분인 지 확인해보는게 좋겠죠?