Introduction
여러가지 리팩토링 기법이 있지만 가장 먼저 번들링 최적화
를 통한 리팩토링을 하려합니다.
다른 리팩토링들은 이후에 다뤄볼 예정입니다.
먼저 번들의 기본인 모듈이 무엇인지, 번들링 최적화가 왜 필요하고, 어떤 방식이 있는지 알아보겠습니다.
모듈이란?
번들의 개념을 알아보기 전에 번들의 기본이 되는 모듈에 대해서 알아보려 합니다.
모듈
은 특정 기능을 수행하는 코드 묶음으로 다른 코드와 독립적으로 재사용 및 관리할 수 있는 단위를 의미합니다.
즉, 우리가 개발할 때 보는 파일 하나하나의 단위가 모듈이라고 할 수 있겠습니다.
모듈 개념이 등장하기 전에는 하나의 파일에 모든 코드가 포함되어 네이밍 충돌, 가독성 저하, 의존성 관리 어려움, 재사용성 부족 등의 문제가 있었습니다.
이러한 문제를 해결하고자 모듈이라는 개념이 등장하였습니다.
이후 모듈 단위로 코드를 관리하기 쉽도록 모듈 시스템
이 등장하였고, ES6, CommonJS 등이 있습니다.
모듈 번들링이 필요한 이유
모듈 시스템의 도입으로 코드를 모듈 단위로 관리할 수 있게 되었지만, 아직 존재하는 문제가 있었습니다.
브라우저는 기본적으로 모듈 시스템을 이해하지 못하기 때문에 모든 모듈을 각각 로드해야합니다.
이 과정에서 네트워크 요청의 과부하가 일어나 성능 저하가 발생하였습니다.
따라서 이를 해결하기 위해 모듈 번들링
이라는 개념이 등장했습니다.
모듈 번들링
은 여러 개의 모듈 파일을 하나의 파일로 합치는 것을 의미하며, 브라우저가 모듈 하나만을 로드할 수 있도록 하여 네트워크 요청을 줄입니다.
번들링 최적화가 필요한 이유
하지만 모듈 번들링 마저도 문제가 있습니다.
파일의 크기가 비대해질 경우, 네트워크 응답 속도가 느려지고 이는 로딩 속도를 증가시켜 사용자 경험에 좋지 않은 영향을 끼칩니다.
이외에도 다양한 이유가 있지만 결국 사용자 경험 개선
과 비용 절감
이 핵심입니다.
번들링 최적화 방식
서론이 길었습니다.
이제 번들링 최적화에는 어떤 방식이 있고, 저는 이 방식들을 어떤 식으로 적용했는지 살펴보겠습니다.
코드 스플리팅
코드 스플리팅은 번들을 여러 청크로 분할하여, 필요한 시점에 필요한 코드만 로드하는 것을 의미합니다
- 웹팩의 config에서 entry point를 설정함으로써 구현 가능합니다.
splitChunks
를 설정하여 중복된 청크를 방지합니다.- 코트 스플리팅의 대상이 되는 컴포넌트를
React.lazy
로 감싸고Suspense
를 상위에 감싸줍니다.라우트 기반 코드 스플리팅
으로 라우트 시 필요한 페이지만 import하고 나머지 페이지들은 lazy loading을 걸어줍니다.컴포넌트 기반 코드 스플리팅
으로 특정 컴포넌트를 렌더링 할 때 해당 컴포넌트의 코드를 분할하여 로드합니다. 저는 모달에 대한 코드 lazy loading을 걸어주었습니다.
트리셰이킹
- 빌드과정에서 사용되지 않는 코드를 삭제합니다.
- 경량화된 라이브러리로 변경합니다.
- moment 라이브러리를 경량화 된 dayjs 라이브러리로 변경하였습니다.
이미지 최적화
jpg
,png
→webp
형식으로 변환하였습니다.- 중요 이미지는
fetchpriority
속성으로 빠르게 로드하도록 하였습니다.
평가
**cra-bundle-analyzer
** 를 이용하여 번들 구조와 크기를 파악하기로 했습니다.
npm install --save-dev cra-bundle-analyzer
npx cra-bundle-analyzer
초기 상태
한 번들에 무려 1.96MB에 달했습니다..
번들을 여러 개의 chunk로 나누기 위해 앞서 설명한 동적 임포트 방식을 사용하였습니다.
페이지 별 lazy loading, 컴포넌트 (ex. 모달) 별 lazy loading을 적용하였습니다.
코드 스플리팅 적용
여러 chunk로 분할된 모습.
하나였던 번들이 여러 개로 분할되었기 때문에 main 번들 또한 1.96MB → 1.38MB로 줄었습니다.
트리 셰이킹 적용
트리 셰이킹을 통해 쓰지 않는 코드를 제거하고, 사진에서도 볼 수 있듯 큰 용량을 차지하는 moment 라이브러리를 dayjs 라이브러리로 경량화하였습니다.
이를 통해 141.17KB → 29.95KB 로 줄였습니다.
이후 이미지를 png
, jpg
에서 webp
형식으로 변환하고, fetchpriority
속성을 통해 빠른 이미지 로드를 적용 등의 이미지 최적화 과정을 거쳤습니다.
이 과정에서 전체 이미지의 크기를 2.495MB → 185.4 KB 로 줄일 수 있었습니다.
로드 속도 & 크기 비교
이러한 최적화 과정들을 통해
초기 번들 로드 속도
를 824ms → 259ms 로 줄일 수 있었고,
번들 크기
또한 957KB → 773KB 로 줄일 수 있었습니다.
Conclusion
코드 스플리팅, 트리 셰이킹, 이미지 최적화를 통한 번들링 최적화 과정을 살펴보았습니다.
처음에 “코드 스플리팅” , “트리 셰이킹” 등의 단어를 보고 알지 못하는 어마무시한 개념이 숨어있을까 지레 겁을 먹기도 했습니다.
하지만 각종 문서들을 찾아보고 GPT와 씨름도 해보니, 결국 번들링 최적화는 번들 사이즈를 줄이려는 목적을 위해 사용하지 않는 자원들을 줄이거나 지우는 것
이 핵심임을 알게 되었습니다.
현재는 단편적인 부분만을 개선했지만 앞으로 모듈 번들러와 관련된 딥한 내용을 토대로 더 효율적인 최적화 방식을 찾아보려합니다.