React 애플리케이션 성능 최적화 기법

React 앱의 성능을 향상시키기 위한 실용적인 최적화 전략과 베스트 프랙티스

Development

React는 강력한 프론트엔드 라이브러리지만, 애플리케이션의 규모가 커지면 성능 이슈가 발생할 수 있습니다. 이 문서에서는 React 애플리케이션의 성능을 최적화하는 다양한 기법과 전략을 살펴봅니다.

불필요한 리렌더링 방지

React.memo 활용

컴포넌트의 props가 변경되지 않았을 때 리렌더링을 방지합니다.

const MyComponent = React.memo(function MyComponent(props) {
  /* 렌더링 로직 */
});

특정 props만 비교하고 싶다면 두 번째 인자에 커스텀 비교 함수를 전달할 수 있습니다:

const MyComponent = React.memo(
  function MyComponent(props) {
    /* 렌더링 로직 */
  },
  (prevProps, nextProps) => {
    // true를 반환하면 리렌더링을 방지합니다
    return prevProps.id === nextProps.id;
  }
);

useMemo와 useCallback 활용

계산 비용이 많이 드는 연산이나 자식 컴포넌트에 전달되는 함수를 메모이제이션합니다.

// 계산 비용이 많이 드는 값 메모이제이션
const memoizedValue = useMemo(() => {
  return computeExpensiveValue(a, b);
}, [a, b]);

// 자식 컴포넌트에 전달되는 함수 메모이제이션
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

코드 분할 (Code Splitting)

React.lazy와 Suspense 활용

필요한 시점에 컴포넌트를 동적으로 로드합니다.

import React, { Suspense } from 'react';

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

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
}

라우트 기반 코드 분할

라우팅 라이브러리(React Router)와 함께 활용하여 각 페이지 단위로 코드를 분할합니다.

import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const Contact = lazy(() => import('./routes/Contact'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

상태 관리 최적화

전역 상태 최소화

애플리케이션 전체에서 필요한 상태만 전역 상태로 관리하고, 컴포넌트 로컬 상태를 적절히 활용합니다.

Context API의 분리

Context API를 사용할 때 모든 상태를 하나의 Context에 넣지 말고, 논리적으로 분리하여 필요한 부분만 리렌더링되도록 합니다.

// 여러 개의 작은 Context 생성
const ThemeContext = React.createContext();
const UserContext = React.createContext();
const SettingsContext = React.createContext();

function App() {
  // 각 Context의 Provider를 중첩하여 사용
  return (
    <ThemeContext.Provider value={theme}>
      <UserContext.Provider value={user}>
        <SettingsContext.Provider value={settings}>
          <MainApp />
        </SettingsContext.Provider>
      </UserContext.Provider>
    </ThemeContext.Provider>
  );
}

가상화 리스트 (Virtualized Lists)

대량의 데이터를 렌더링할 때 화면에 보이는 항목만 렌더링하여 성능을 개선합니다.

import { FixedSizeList } from 'react-window';

function VirtualizedList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].name}
    </div>
  );

  return (
    <FixedSizeList
      height={500}
      width={300}
      itemCount={items.length}
      itemSize={35}
    >
      {Row}
    </FixedSizeList>
  );
}

이미지 최적화

지연 로딩(Lazy Loading)

화면에 보이는 이미지만 로드합니다.

import { LazyLoadImage } from 'react-lazy-load-image-component';

function MyImage({ src, alt }) {
  return (
    <LazyLoadImage
      src={src}
      alt={alt}
      effect="blur"
      placeholderSrc={smallImageSrc}
    />
  );
}

이미지 포맷 최적화

WebP와 같은 최신 이미지 포맷을 사용하고, 필요에 맞는 적절한 크기로 이미지를 제공합니다.

<picture>
  <source srcSet="image.webp" type="image/webp" />
  <source srcSet="image.jpg" type="image/jpeg" />
  <img src="image.jpg" alt="Description" width="800" height="600" />
</picture>

웹 성능 측정 도구

React Developer Tools

React 개발자 도구의 Profiler 탭을 사용하여 컴포넌트의 렌더링 시간과 빈도를 측정합니다.

Lighthouse

Google의 Lighthouse를 사용하여 웹사이트의 전반적인 성능, 접근성, SEO 등을 측정합니다.

Web Vitals

Core Web Vitals(LCP, FID, CLS)를 측정하여 사용자 경험 지표를 추적합니다.

import { getCLS, getFID, getLCP } from 'web-vitals';

function sendToAnalytics(metric) {
  const { name, value } = metric;
  console.log(`${name}: ${value}`);
  // 분석 서비스로 데이터 전송
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getLCP(sendToAnalytics);

결론

React 애플리케이션 성능 최적화는 단일 기법이 아닌 여러 기법의 조합으로 이루어집니다. 항상 측정 가능한 지표를 기반으로 최적화하고, 실제 사용자 경험 향상에 초점을 맞추세요. 모든 최적화 기법을 동시에 적용하기보다는 가장 큰 성능 향상을 가져올 수 있는 부분부터 점진적으로 적용하는 것이 효과적입니다.

최초 생성일: 2024. 1. 28.

최종 수정일: 2024. 2. 22.