리액트 성능 최적화 기법



리액트 성능 최적화 기법


리액트(React)는 사용자 인터페이스를 구축하기 위한 자바스크립트 라이브러리로, 컴포넌트 기반 구조를 통해 복잡한 애플리케이션을 효율적으로 관리할 수 있습니다. 하지만 애플리케이션의 규모가 커짐에 따라 성능 문제가 발생할 수 있습니다. 이 포스팅에서는 리액트 애플리케이션의 성능을 최적화하는 다양한 방법에 대해 살펴보겠습니다.


리액트 성능 최적화의 중요성


성능 최적화는 사용자 경험을 향상시키고, 애플리케이션의 반응성을 높이는 데 필수적입니다. 성능이 좋은 애플리케이션은 더 빠른 로드 시간과 더 부드러운 사용자 인터페이스를 제공하며, 이는 사용자 만족도와 유지율을 높이는 데 큰 역할을 합니다.


불필요한 렌더링 방지


리액트 컴포넌트는 상태나 props가 변경될 때마다 리렌더링됩니다. 따라서 불필요한 렌더링을 방지하는 것이 중요합니다.


React.memo 사용


React.memo는 컴포넌트를 메모이제이션하여 props가 변경되지 않는 한 리렌더링을 방지합니다.


import React from 'react';

const MyComponent = React.memo(({ name }) => {
  console.log('렌더링');
  return <div>{name}</div>;
});

export default MyComponent;

위 예제에서 MyComponent는 props가 변경되지 않는 한 리렌더링되지 않습니다.


shouldComponentUpdate 사용


클래스형 컴포넌트에서는 shouldComponentUpdate 메서드를 사용하여 렌더링 여부를 결정할 수 있습니다.


import React, { Component } from 'react';

class MyComponent extends Component {
  shouldComponentUpdate(nextProps) {
    return nextProps.name !== this.props.name;
  }

  render() {
    console.log('렌더링');
    return <div>{this.props.name}</div>;
  }
}

export default MyComponent;

위 예제에서 MyComponentname props가 변경될 때만 리렌더링됩니다.


컴포넌트 분할


큰 컴포넌트를 작은 컴포넌트로 분할하면 각 컴포넌트의 상태와 props 변경 시 리렌더링 범위를 최소화할 수 있습니다.


import React from 'react';

const Header = () => <header>헤더</header>;
const Footer = () => <footer>푸터</footer>;

const Page = () => (
  <div>
    <Header />
    <main>메인 콘텐츠</main>
    <Footer />
  </div>
);

export default Page;

위 예제에서 HeaderFooter 컴포넌트는 Page 컴포넌트와 분리되어 각각 독립적으로 리렌더링됩니다.


코드 분할


코드 분할은 애플리케이션의 초기 로딩 시간을 줄이고, 사용자가 필요로 할 때만 필요한 코드를 로드하는 방법입니다. 이를 통해 애플리케이션의 성능을 크게 향상시킬 수 있습니다.


React.lazy 사용


React.lazySuspense를 사용하여 동적 import를 구현할 수 있습니다.


import React, { Suspense } from 'react';

const OtherComponent = React.lazy(() => import('./OtherComponent'));

const MyComponent = () => (
  <div>
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  </div>
);

export default MyComponent;

위 예제에서 OtherComponent는 필요할 때만 로드되며, 로드 중에는 Loading... 메시지가 표시됩니다.


성능 최적화를 위한 훅 사용


리액트는 성능 최적화를 돕기 위해 몇 가지 훅을 제공합니다.


useCallback 사용


useCallback 훅은 함수형 컴포넌트에서 함수를 메모이제이션하여 불필요한 렌더링을 방지합니다.


import React, { useState, useCallback } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return <button onClick={handleClick}>Count: {count}</button>;
};

export default MyComponent;

useMemo 사용


useMemo 훅은 연산 비용이 높은 작업의 결과를 메모이제이션하여 성능을 최적화합니다.


import React, { useState, useMemo } from 'react';

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const expensiveCalculation = (num) => {
    console.log('비용이 많이 드는 계산');
    return num * 2;
  };

  const result = useMemo(() => expensiveCalculation(count), [count]);

  return (
    <div>
      <p>Result: {result}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default MyComponent;

가상화 리스트


리스트 렌더링 시, 많은 항목을 한꺼번에 렌더링하면 성능이 저하될 수 있습니다. 가상화 리스트를 사용하면 보이는 항목만 렌더링하여 성능을 최적화할 수 있습니다.


react-window 사용


react-window는 리스트와 그리드 컴포넌트의 가상화를 위한 라이브러리입니다.


import React from 'react';
import { FixedSizeList as List } from 'react-window';

const MyComponent = () => {
  const items = Array.from({ length: 1000 }, (_, index) => `Item ${index}`);

  return (
    <List
      height={150}
      itemCount={items.length}
      itemSize={35}
      width={300}
    >
      {({ index, style }) => <div style={style}>{items[index]}</div>}
    </List>
  );
};

export default MyComponent;

위 예제에서 react-window는 보이는 항목만 렌더링하여 성능을 최적화합니다.


불변성 유지


리액트는 상태가 변경될 때마다 리렌더링을 트리거합니다. 상태를 불변으로 유지하면 변경이 발생한 경우에만 리렌더링을 수행할 수 있습니다.


불변성 유지 예제


import React, { useState } from 'react';

const MyComponent = () => {
  const [items, setItems] = useState([1, 2, 3]);

  const addItem = () => {
    setItems([...items, items.length + 1]);
  };

  return (
    <div>
      <ul>
        {items.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
      <button onClick={addItem}>Add Item</button>
    </div>
  );
};

export default MyComponent;

위 예제에서 setItems 함수는 기존 배열을 복사하여 새로운 항목을 추가합니다.


주요 포인트 요약 및 추가 학습 자료


이 포스팅에서는 리액트 애플리케이션의 성능을 최적화하는 다양한 방법에 대해 살펴보았습니다. 불필요한 렌더링을 방지하고, 컴포넌트를 분할하며, 코드 분할과 가상화 리스트를 사용하는 것이 주요 최적화 기법입니다. 추가로 학습할 자료는 다음 링크를 참고하시기 바랍니다:


다음 이전