프론트엔드 기초 다시 쌓기 챌린지 4일차.
Day 2에서 "빌드하면 파일이 합쳐진다"는 걸 배웠다면,
오늘은 "왜 합쳐야 하는지", "누가 합쳐주는지", "안 쓰는 코드는 어떻게 되는지" 를 깊이 파헤쳤다.
그리고 "네트워크가 뭐야?", "번들 사이즈가 크면 뭐가 느려지는 거야?" 라는 궁금증까지 해결했다.
프로젝트에 파일이 보통 100~500개 있다.
이걸 그대로 배포하면?
사용자가 홈페이지 접속
→ 브라우저: "HTML 주세요" (1번 요청)
→ 브라우저: "Header.tsx 주세요" (2번 요청)
→ 브라우저: "Footer.tsx 주세요" (3번 요청)
→ 브라우저: "api.ts 주세요" (4번 요청)
→ ...
→ 총 50개 요청 😱
요청 하나하나에 네트워크 연결, 파일 전송, 파싱이 필요하다.
파일 자체가 가벼워도 요청 횟수 때문에 느려진다.
17개 파일 → 3개로 합침
main.js ← 핵심 코드 전부
vendor.js ← 라이브러리 (react, next 등)
styles.css ← CSS 전부
→ 총 4개 요청 ⚡ (50번 → 4번)
비유: 이사할 때 물건을 하나씩 옮기면 200트립,
박스에 묶어서 옮기면 3트립. 번들링은 "박스에 묶는 것" 이다.
등장: 2012년 (가장 오래됨)
비유: 만능 이사 업체 — 뭐든 다 해줌, 근데 좀 느림
등장: 2020년
비유: 퀵서비스 배달 — 엄청 빠름, 가볍고 심플
개발 서버 시작 속도 (파일 100개 기준)
Webpack: 10초
Vite: 0.5초
등장: 2020년
비유: 로켓 배달 — 미친 속도, 단순한 일만 잘함
| 구분 | Webpack | Vite | esbuild |
|---|---|---|---|
| 속도 | 느림 | 빠름 | 미친듯이 빠름 |
| 설정 | 복잡 | 간단 | 매우 간단 |
| 생태계 | 거대함 | 커지는 중 | 작음 |
| 비유 | 만능 이사 업체 | 퀵서비스 배달 | 로켓 배달 |
실무 기준:
나무를 흔들면 죽은 잎이 떨어진다.
코드를 빌드할 때 안 쓰는 코드가 자동으로 삭제되는 것.
// lodash에는 함수가 300개 있음
// 내가 쓰는 건 딱 2개
import { debounce, throttle } from 'lodash'
Tree Shaking 없으면: 함수 300개 전부 포함 → 70 KB
Tree Shaking 있으면: 2개만 포함 → 3 KB
67 KB 절약! 사용자가 안 쓰는 코드를 안 받아도 된다.
// ❌ 이렇게 쓰면 Tree Shaking 안 됨
import _ from 'lodash'
_.debounce(...)
// → "lodash 전체를 가져와" 라는 뜻
// → 번들러: "뭘 쓸지 모르니까 다 넣어야지"
// ✅ 이렇게 써야 Tree Shaking 됨
import { debounce } from 'lodash'
debounce(...)
// → "debounce만 가져와" 라는 뜻
// → 번들러: "debounce만 넣으면 되네!"
이게 named import vs default import의 차이.
앞으로 라이브러리 import 할 때 항상 의식하자.
$ yarn build
Route (pages) Size First Load JS
─────────────────────────────────────────────────────────
○ / 5.2 kB 87.3 kB
○ /about 2.1 kB 84.2 kB
+ First Load JS shared by all 82.1 kB
| 용어 | 의미 |
|---|---|
| Size | 그 페이지에서만 쓰는 JS 크기 |
| First Load JS | 그 페이지 처음 열 때 받는 총 JS |
✅ First Load JS < 100 KB → 좋음
⚠️ First Load JS 100-200 KB → 개선 필요
❌ First Load JS > 200 KB → 문제 있음
번들 사이즈를 눈으로 볼 수 있는 도구.
큰 네모 박스일수록 용량이 큰 파일이다.
비정상적으로 큰 박스를 찾으면 최적화 대상.
moment.js → 전체 크기 약 300 KB 😱
전세계 언어팩이 다 포함돼서 엄청 무거움
해결: day.js (2 KB) 또는 date-fns로 교체
// ❌ 70 KB 전부 불러옴
import _ from 'lodash'
// ✅ 필요한 것만 (3 KB)
import { debounce } from 'lodash-es'
// ❌ 아이콘 수천 개 전부 불러옴
import * as Icons from 'react-icons'
// ✅ 필요한 것만
import { FiSearch, FiHeart } from 'react-icons/fi'
Day 3에서 Network 탭을 배우면서 궁금한 점이 생겼다.
"네트워크가 브라우저가 동작하는 과정인가?"
네트워크 = 컴퓨터끼리 데이터를 주고받는 통로
브라우저 동작 과정 자체가 아니라, "데이터가 이동하는 도로" 같은 개념이다.
당신 (브라우저) ←──전화선──→ 친구 (서버)
↑
이게 네트워크!
1. 사용자가 URL 입력
2. 🌐 네트워크: 서버한테 파일 요청 → 파일 받음 ← Network 탭
3. 🎨 렌더링: 받은 파일로 화면 그림 ← Performance 탭
4. ⚙️ JS 실행: 기능 동작 ← Console 탭
5. 📡 추가 요청: API 호출 등 ← Network 탭
네트워크는 2번과 5번 단계. 전체 과정 중 "파일을 주고받는 부분" 만 담당한다.
"빌드 속도가 느려지는 건가? 사용자 로딩이 느려지는 건가?"
결론부터 말하면 사용자 로딩이 느려진다.
[1단계] 다운로드 : 서버에서 파일을 받는 시간
[2단계] 파싱(해석) : 받은 코드를 브라우저가 읽는 시간
[3단계] 실행+렌더링 : 코드 실행해서 화면 그리는 시간
번들 사이즈가 크면 3단계 전부 느려진다.
1단계: 다운로드 느려짐
100 KB → 0.1초 / 500 KB → 0.5초
와이파이에서는 차이 적지만, 지하철 4G에서는 체감 엄청남
2단계: 파싱 느려짐
100 KB 읽기 → 50ms / 500 KB 읽기 → 250ms
이 시간 동안 사용자는 빈 화면 봄
3단계: 실행+렌더링 느려짐
JS 코드가 실행되어야 React 컴포넌트가 화면에 그려짐
코드 많을수록 실행 시간도 길어짐
번들 100 KB:
다운로드(0.1초) → 파싱(0.05초) → 실행(0.05초) = 총 0.2초 ⚡
번들 500 KB:
다운로드(0.5초) → 파싱(0.25초) → 실행(0.2초) = 총 0.95초 😑
번들 2 MB:
다운로드(2초) → 파싱(1초) → 실행(0.5초) = 총 3.5초 😱 → 이탈!
번들 사이즈가 커도 빌드 속도에는 큰 영향 없다.
빌드 속도는 파일 갯수나 번들러 종류(Webpack vs Vite)에 더 영향받는다.
빌드 속도 → 개발자가 기다리는 시간 (번들 사이즈 영향 적음)
사용자 로딩 → 사용자가 기다리는 시간 (번들 사이즈 영향 큼 ⭐)
Day 1: 개발 → 빌드 → 배포, .env는 서버마다 따로
↓
Day 2: 빌드하면 컴파일 + 번들링 + 최적화 + 정적 생성
↓
Day 3: 브라우저가 번들링된 파일을 받아서 캐시, CDN으로 속도 향상
↓
Day 4: 번들링이 없으면 요청 50번, 있으면 4번
Tree Shaking으로 안 쓰는 코드 제거
번들 사이즈가 크면 다운로드+파싱+실행 전부 느려짐
→ 전부 "코드를 사용자에게 빠르고 효율적으로 전달"이라는 하나의 목적
yarn build 로그, bundle-analyzer이번 Day 4에서 가장 큰 깨달음은 "import 한 줄이 번들 사이즈를 좌우한다" 는 것이다.
import _ from 'lodash' // 70 KB
import { debounce } from 'lodash' // 3 KB
이 한 줄 차이가 사용자 로딩 속도에 영향을 준다니.
지금까지 아무 생각 없이 import 해왔는데, 앞으로는 의식적으로 named import를 쓸 것이다.
그리고 "네트워크"라는 단어를 정확히 몰랐는데, 이번에 확실히 잡았다.
"컴퓨터끼리 데이터를 주고받는 통로". 단순하지만 이 한 문장이 앞으로 배울 HTTP, TCP/IP, DNS 개념의 기초가 된다.
#프론트엔드 #번들링 #Webpack #Vite #TreeShaking #번들사이즈 #2년차개발자 #기초다시쌓기