본문 바로가기
코딩이야기𖦹/React

📌 React 성능 최적화 정리

by Dev디자인 2025. 4. 24.

React 프로젝트를 최적화하기 위해 꼭 알아야 할 개념들을 정리했음.
이 글에서는 번들링과 코드 스플리팅, 그리고 입력 이벤트 제어 기법인 debouncethrottle을 실제 예제와 함께 정리했다.

📦 번들링(Bundling)이란?

여러 개의 파일을 하나로 묶는 작업

React 프로젝트를 개발하면 자바스크립트 파일, CSS, 이미지 등 다양한 리소스가 생성됨. 번들링은 이러한 리소스들을 하나의 파일로 묶어서 브라우저가 로딩할 파일의 수를 줄이고, HTTP 요청 횟수를 줄여 속도 향상을 가능하게 함.

🔧 대표 번들링 도구

  • Vite
  • Rollup
  • CRA (Create React App)
  • Webpack

✅ 번들링의 효과

  • HTTP 요청 수 감소 → 성능 향상
  • 코드 압축 → 파일 크기 축소
  • 사용되지 않는 코드 제거(트리 쉐이킹) → 최적화

✂️ 코드 스플리팅(Code Splitting)이란?

앱의 코드를 필요한 순간에 나눠서 불러오는 기법

기본적으로 번들링하면 전체 코드가 하나의 파일로 묶임.

문제는 앱이 커질수록 처음부터 모든 기능을 불러오느라 초기 로딩이 느려진다는 점.

코드 스플리팅은 이 문제를 해결하기 위해, 필요한 기능만 그때그때 불러오도록 앱을 여러 조각으로 나누는 방법임.

✅ 코드 스플리팅의 효과

  • 초기 로딩 속도 개선
  • 불필요한 코드 로드 방지
  • 데이터 전송 비용 절감

⚙️ React의 lazy와 Suspense로 코드 스플리팅하기

React에서는 컴포넌트를 동적으로 불러올 수 있게 해주는 기능이 있음.

🔸 React.lazy()

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

TestComponent를 처음부터 불러오지 않고, 필요할 때만 로드

🔸 Suspense

<Suspense fallback={<div>로딩 중...</div>}>
  <TestComponent />
</Suspense>

TestComponent를 불러오는 동안 보여줄 UI를 설정함

✅ 전체 예제 코드 (한눈에 보기)

 
// TestComponent.jsx
function TestComponent() {
  return (
    <div>
      <h2>Test 컴포넌트가 로드되었습니다!</h2>
      <p>이건 lazy와 Suspense로 불러온 컴포넌트임</p>
    </div>
  );
}
export default TestComponent;
// App.jsx
import React, { lazy, Suspense, useState } from 'react';

const TestComponent = lazy(() => import('./TestComponent'));

function App() {
  const [show, setShow] = useState(false);

  return (
    <div>
      <h1>React 코드 스플리팅</h1>
      <button onClick={() => setShow(true)}>컴포넌트 로드하기</button>

      {show && (
        <Suspense fallback={<div>로딩 중...</div>}>
          <TestComponent />
        </Suspense>
      )}
    </div>
  );
}

💡 동작 흐름

  1. 앱을 실행해도 TestComponent는 로드되지 않음
  2. 버튼을 누르면 → 비동기적으로 TestComponent가 로드됨
  3. 로딩이 끝나기 전까지는 fallback인 "로딩 중..." 표시

⏱ Debounce란?

연속 입력 중 마지막 입력 후 일정 시간 대기한 뒤 실행하는 방식

🔍 사용 예

  • 사용자가 검색창에 글을 입력할 때
  • 매 글자마다 검색 요청 보내면 서버에 부담
    → 그래서 입력이 끝나고 잠깐 기다렸다가 실행

✅ 직접 만든 debounce 함수

const debounce = (func, delay) => {
  let timer;
  return (...args) => {
    clearTimeout(timer); // 타이머 초기화
    timer = setTimeout(() => func(...args), delay); // delay 이후 실행
  };
};

✅ 예제 코드

const handleDebounce = debounce((value) => {
  console.log('[Debounce]', value);
}, 500);

<input
  type="text"
  placeholder="검색어를 입력하세요"
  onChange={(e) => handleDebounce(e.target.value)}
/>

💡 동작 설명

  • 사용자가 입력 중에는 실행 안 됨
  • 입력을 멈추고 0.5초 동안 아무 일도 없으면 콘솔에 값이 출력됨

⏲ Throttle이란?

일정 시간 간격마다 한 번씩만 실행되는 방식

🔍 사용 예

  • 마우스 이동, 스크롤 이벤트
  • 너무 자주 실행되면 성능에 부담
    → 그래서 간격을 두고 실행

✅ 직접 만든 throttle 함수

const throttle = (func, delay) => {
  let last = 0;
  return (...args) => {
    const now = Date.now();
    if (now - last > delay) {
      func(...args);
      last = now;
    }
  };
};

✅ 예제 코드

const handleThrottle = throttle((value) => {
  console.log('[Throttle]', value);
}, 500);

<input
  type="text"
  placeholder="입력해 보세요"
  onChange={(e) => handleThrottle(e.target.value)}
/>

💡 동작 설명

  • 입력이 계속되더라도 0.5초마다 한 번씩만 실행됨
  • 사용자가 아무리 빨리 입력해도 콘솔 출력은 일정 간격으로만 찍힘

⚔️ Debounce vs Throttle 차이점

구분 Debounce Throttle
실행 시점 입력 멈춘 후 일정 시간 지나서 실행 일정 시간마다 실행
실행 빈도 1번 n초마다 1번
사용 예시 검색창 입력, 자동완성 스크롤 이벤트, 마우스 이동
목표 최소 실행 횟수 간격 유지하며 지속 실행

✅ 마무리하며

  • 🔗 번들링(Bundling):
    여러 개의 파일을 하나로 묶어 HTTP 요청 수를 줄이고 성능을 향상시켰음.
  • ✂️ 코드 스플리팅(Code Splitting):
    앱의 코드를 조각내어 필요한 시점에만 로딩되도록 하여 초기 로딩 속도를 줄였음.
  • ⚙️ React.lazy() + Suspense:
    컴포넌트를 동적으로 불러오는 기능을 구현하여 컴포넌트 단위 코드 스플리팅을 실현했음.
  • Debounce:
    입력이 끝난 뒤 일정 시간 후에만 실행되도록 하여 불필요한 함수 호출을 방지했음.
  • Throttle:
    일정 시간마다 한 번씩만 함수가 실행되도록 하여 과도한 연속 이벤트 처리 부하를 줄였음.

최근댓글

최근글

skin by © 2024 ttuttak