React 성능 최적화

Lazy Loading, Suspense, 메모이제이션으로 성능 향상

React고급
6시간
3개 항목
학습 진행률0 / 3 (0%)

학습 항목

1. React
초급
Performance|최적화|실전|프로젝트|가이드
퀴즈튜토리얼
2. React
React|Suspense|Lazy|Loading|완벽|가이드
퀴즈튜토리얼
3. React
Next.js|Metadata|API|SEO|최적화
퀴즈튜토리얼
1 / 3

이미지 로딩 중...

Performance 최적화 실전 프로젝트 가이드 - 슬라이드 1/13

Performance 최적화 실전 프로젝트 가이드

웹 애플리케이션의 성능을 극대적으로 향상시키는 실전 최적화 기법을 다룹니다. 렌더링 최적화부터 네트워크 성능, 번들 사이즈 최적화까지 실무에서 바로 적용 가능한 패턴들을 배웁니다.


카테고리:React
언어:JavaScript
난이도:beginner
메인 태그:#React
서브 태그:
#Performance#Optimization#Memoization#LazyLoading

들어가며

이 글에서는 Performance 최적화 실전 프로젝트 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. React.memo로_불필요한_리렌더링_방지
  2. useMemo로_비용이_큰_연산_캐싱
  3. useCallback으로_함수_재생성_방지
  4. Code_Splitting으로_초기_로딩_속도_개선
  5. Virtual_List로_대용량_데이터_렌더링
  6. Image_Lazy_Loading으로_네트워크_절약
  7. Debounce로_API_호출_최적화
  8. Web_Worker로_무거운_작업_분리
  9. CSS_in_JS_최적화_with_Styled_Components
  10. React_DevTools_Profiler로_성능_측정
  11. Bundle_Analyzer로_번들_크기_최적화
  12. Intersection_Observer로_스크롤_이벤트_최적화

1. React.memo로_불필요한_리렌더링_방지

개요

컴포넌트의 props가 변경되지 않으면 리렌더링을 건너뛰어 성능을 최적화합니다.

코드 예제

const UserCard = React.memo(({ name, email }) => {
  console.log('UserCard rendered');
  return (
    <div>
      <h3>{name}</h3>
      <p>{email}</p>
    </div>
  );
});

설명

props가 동일하면 이전 렌더링 결과를 재사용하여 불필요한 렌더링을 방지합니다.


2. useMemo로_비용이_큰_연산_캐싱

개요

복잡한 계산 결과를 메모이제이션하여 매 렌더링마다 재계산하지 않도록 합니다.

코드 예제

const FilteredList = ({ items, query }) => {
  const filtered = useMemo(() => {
    return items.filter(item =>
      item.name.toLowerCase().includes(query.toLowerCase())
    );
  }, [items, query]);

  return <ul>{filtered.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
};

설명

items나 query가 변경될 때만 필터링을 다시 수행하여 성능을 개선합니다.


3. useCallback으로_함수_재생성_방지

개요

콜백 함수를 메모이제이션하여 자식 컴포넌트의 불필요한 리렌더링을 방지합니다.

코드 예제

const TodoList = () => {
  const [todos, setTodos] = useState([]);

  const addTodo = useCallback((text) => {
    setTodos(prev => [...prev, { id: Date.now(), text }]);
  }, []);

  return <TodoForm onAdd={addTodo} />;
};

설명

addTodo 함수가 매번 새로 생성되지 않아 TodoForm의 리렌더링을 최소화합니다.


4. Code_Splitting으로_초기_로딩_속도_개선

개요

React.lazy와 Suspense를 사용하여 필요한 시점에만 컴포넌트를 로드합니다.

코드 예제

const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

설명

각 페이지를 별도 번들로 분리하여 초기 로딩 시간을 단축시킵니다.


5. Virtual_List로_대용량_데이터_렌더링

개요

화면에 보이는 항목만 렌더링하여 수천 개의 데이터도 빠르게 처리합니다.

코드 예제

import { FixedSizeList } from 'react-window';

const VirtualList = ({ items }) => (
  <FixedSizeList
    height={400}
    itemCount={items.length}
    itemSize={50}
    width="100%"
  >
    {({ index, style }) => (
      <div style={style}>{items[index].name}</div>
    )}
  </FixedSizeList>
);

설명

뷰포트에 보이는 항목만 DOM에 렌더링하여 메모리와 성능을 최적화합니다.


6. Image_Lazy_Loading으로_네트워크_절약

개요

이미지를 필요한 시점에만 로드하여 초기 페이지 로딩 속도를 향상시킵니다.

코드 예제

const OptimizedImage = ({ src, alt }) => (
  <img
    src={src}
    alt={alt}
    loading="lazy"
    decoding="async"
    style={{ width: '100%', height: 'auto' }}
  />
);

설명

loading="lazy" 속성으로 이미지가 뷰포트에 가까워질 때만 로드됩니다.


7. Debounce로_API_호출_최적화

개요

연속된 이벤트를 그룹화하여 불필요한 API 호출을 줄입니다.

코드 예제

const SearchBox = () => {
  const [query, setQuery] = useState('');

  const debouncedSearch = useMemo(
    () => debounce((value) => {
      fetch(`/api/search?q=${value}`).then(/* ... */);
    }, 500),
    []
  );

  return <input onChange={(e) => debouncedSearch(e.target.value)} />;
};

설명

사용자가 타이핑을 멈춘 후 500ms 후에만 검색 API를 호출합니다.


8. Web_Worker로_무거운_작업_분리

개요

메인 스레드를 블로킹하지 않고 백그라운드에서 복잡한 연산을 처리합니다.

코드 예제

const worker = new Worker('calculator.worker.js');

const HeavyComputation = () => {
  const calculate = (data) => {
    worker.postMessage(data);
    worker.onmessage = (e) => {
      console.log('Result:', e.data);
    };
  };

  return <button onClick={() => calculate([1,2,3])}>Calculate</button>;
};

설명

복잡한 계산을 별도 스레드에서 실행하여 UI가 멈추지 않습니다.


9. CSS_in_JS_최적화_with_Styled_Components

개요

동적 스타일을 효율적으로 처리하여 불필요한 CSS 재생성을 방지합니다.

코드 예제

const Button = styled.button`
  background: ${props => props.primary ? '#007bff' : '#6c757d'};
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
`;

const OptimizedButton = memo(Button);

설명

스타일 컴포넌트를 메모이제이션하여 props 변경 시에만 재생성합니다.


10. React_DevTools_Profiler로_성능_측정

개요

컴포넌트별 렌더링 시간을 측정하여 병목 지점을 찾아냅니다.

코드 예제

import { Profiler } from 'react';

<Profiler id="Dashboard" onRender={(id, phase, actualDuration) => {
  console.log(`${id} (${phase}) took ${actualDuration}ms`);
}}>
  <Dashboard />
</Profiler>

설명

각 컴포넌트의 렌더링 성능을 측정하여 최적화가 필요한 부분을 파악합니다.


11. Bundle_Analyzer로_번들_크기_최적화

개요

번들에 포함된 모듈의 크기를 시각화하여 불필요한 의존성을 제거합니다.

코드 예제

// package.json
{
  "scripts": {
    "analyze": "source-map-explorer 'build/static/js/*.js'"
  }
}

// 터미널에서 실행
// npm run build && npm run analyze

설명

빌드된 번들을 분석하여 큰 라이브러리를 찾아 tree-shaking이나 대체를 검토합니다.


12. Intersection_Observer로_스크롤_이벤트_최적화

개요

스크롤 이벤트 대신 Intersection Observer를 사용하여 성능을 향상시킵니다.

코드 예제

const LazyComponent = () => {
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) setIsVisible(true);
    });
    observer.observe(ref.current);
  }, []);

  return <div ref={ref}>{isVisible && <HeavyContent />}</div>;
};

설명

요소가 뷰포트에 들어올 때만 무거운 컴포넌트를 렌더링하여 성능을 개선합니다.


마치며

이번 글에서는 Performance 최적화 실전 프로젝트 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#React #Performance #Optimization #Memoization #LazyLoading

#React#Performance#Optimization#Memoization#LazyLoading