리액트의 동등 비교와 객체 타입

shooting star·2024년 7월 9일
post-thumbnail

리액트의 동등 비교와 객체 타입

리액트는 동등 비교를 할 때 Object.is를 사용합니다. 이는 ES6에서 새롭게 도입된 비교 문법으로, 기존의 동등 비교 연산자 ===가 가지는 몇 가지 한계를 극복하기 위해 만들어졌습니다. 그러나 여전히 객체 간 비교에서는 자바스크립트의 특징으로 인해 ===와 동일하게 동작합니다.

원시 타입과 객체 타입의 차이점

원시 타입과 객체 타입의 가장 큰 차이점은 값을 저장하는 방식입니다. 원시 값은 변경 불가능한 형태로 저장되지만, 객체는 프로퍼티를 삭제, 추가, 수정할 수 있어 변경 가능한 형태로 저장됩니다. 이 차이는 동등 비교 시 큰 영향을 미칩니다. 객체는 값을 저장하는 대신 참조를 저장하기 때문에, 동일한 객체를 선언하더라도 저장하는 순간 다른 참조를 바라보게 되어 false를 반환하게 됩니다.

자바스크립트 개발자는 객체 간 비교 시 내부의 값이 같더라도 결과는 대부분 true가 아닐 수 있다는 것을 인지해야 합니다. Object.is를 사용하더라도 객체 비교에서는 별 차이가 없습니다. 객체 비교는 여전히 참조를 비교하는 것이기 때문입니다.

리액트에서의 동등 비교

리액트에서 사용하는 동등 비교는 =====가 아닌 Object.is입니다. 이는 ES6에서 제공하는 기능이기 때문에 리액트에서는 이를 구현한 폴리필을 함께 사용합니다. 리액트에서는 이 Object.is를 기반으로 동등 비교를 하는 shallowEqual이라는 함수를 만들어 사용합니다. 이 shallowEqual은 의존성 비교 등 리액트의 다양한 동등 비교가 필요한 곳에서 사용됩니다.

리액트에서의 비교를 요약하자면 Object.is로 먼저 비교를 수행한 다음에 Object.is에서 수행하지 못하는 비교, 즉 객체 간 얕은 비교를 한 번 더 수행합니다. 객체 간 얕은 비교란 객체의 첫 번째 깊이에 존재하는 값만 비교한다는 것을 의미합니다.

JSX props와 얕은 비교

리액트에서 사용하는 JSX props는 객체입니다. 따라서 이 props만 일차적으로 비교하면 됩니다. 그러나 props가 깊어지는 경우, 즉 한 객체 안에 또 다른 객체가 있을 경우 React.memo는 컴포넌트에 실제로 변경된 값이 없음에도 불구하고 메모이제이션된 컴포넌트를 반환하지 못합니다. 이는 1 depth를 초과하면 비교가 안 되기 때문입니다.

이러한 자바스크립트를 기반으로 한 리액트의 함수형 프로그래밍 모델에서도 언어적 한계를 뛰어넘을 수 없으므로 얕은 비교만 사용해 필요한 기능을 구현하고 있습니다. 이러한 자바스크립트의 특징을 잘 숙지한다면 향후 함수 컴포넌트에서 사용되는 훅의 의존성 배열과 비교 렌더링 방지를 넘어선 useMemouseCallback의 필요성, 렌더링 최적화를 위해 꼭 필요한 React.memo를 올바르게 작동시키기 위해 고려해야 할 것들을 쉽게 이해할 수 있을 것입니다.

리액트의 최적화를 위해서는 얕은 비교의 한계를 이해하고 이를 바탕으로 컴포넌트 설계를 해야 합니다. 이를 통해 불필요한 렌더링을 줄이고 애플리케이션의 성능을 향상시킬 수 있습니다.

예제

다음은 shallowEqual을 사용하여 리액트 컴포넌트를 최적화하는 예제입니다.

import React, { memo } from 'react';
import shallowEqual from 'shallowequal';

const MyComponent = ({ user }) => {
  console.log('MyComponent rendered');
  return <div>{user.name}</div>;
};

// React.memo를 사용하여 컴포넌트를 메모이제이션합니다.
// shallowEqual을 통해 객체의 얕은 비교를 수행합니다.
const MemoizedComponent = memo(MyComponent, (prevProps, nextProps) => {
  return shallowEqual(prevProps.user, nextProps.user);
});

const App = () => {
  const [user, setUser] = React.useState({ name: 'John', age: 25 });

  return (
    <div>
      <MemoizedComponent user={user} />
      <button onClick={() => setUser({ name: 'John', age: 25 })}>
        Update User
      </button>
    </div>
  );
};

export default App;

위의 예제에서 MemoizedComponentshallowEqual을 사용하여 user 객체의 얕은 비교를 수행합니다. 버튼을 클릭하여 user 객체를 동일한 값으로 업데이트할 때, shallowEqual이 이전과 다음 user 객체를 비교하여 동일하다고 판단하므로 MemoizedComponent는 다시 렌더링되지 않습니다. 이는 불필요한 렌더링을 방지하여 성능을 최적화하는 좋은 방법입니다.

0개의 댓글