React 프로젝트를 최적화하기 위해 꼭 알아야 할 개념들을 정리했음.
이 글에서는 번들링과 코드 스플리팅, 그리고 입력 이벤트 제어 기법인 debounce와 throttle을 실제 예제와 함께 정리했다.
📦 번들링(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>
);
}
💡 동작 흐름
- 앱을 실행해도 TestComponent는 로드되지 않음
- 버튼을 누르면 → 비동기적으로 TestComponent가 로드됨
- 로딩이 끝나기 전까지는 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:
일정 시간마다 한 번씩만 함수가 실행되도록 하여 과도한 연속 이벤트 처리 부하를 줄였음.
'코딩이야기𖦹 > React' 카테고리의 다른 글
| 📌 React 렌더링 최적화: memo, useMemo, useCallback 완전정복하기 (0) | 2025.04.23 |
|---|---|
| 📌 복잡한 상태관리를 깔끔하게! Redux 개념 정리 (0) | 2025.04.22 |
| 📌 Context API로 전역 상태 관리 하기 (0) | 2025.04.21 |
| 📌 React 앱을 가볍게! 전역 상태 관리로 구조 최적화하기 (0) | 2025.04.18 |
| 📌 Tailwind CSS 진짜 편한가? (0) | 2025.04.17 |