CRA를 사용하지 않고 직접 Webpack과 Babel을 세팅한 프로젝트를 진행중이다.
프로젝트의 구현이 마무리 단계가 되어 최적화를 위해 라이트하우스를 돌려보았다.
위 사진에서 보다시피 성능적인 부분에서의 개선이 필요했다.
webpack-bundle-analyzer 플러그인을 사용해 빌드 시 번들에서 어떤 요소가 용량을 많이 차지하고 있는지 확인을 해보니 firebase와 lodash가 압도적인 크기를 자랑하고 있었다.
lodash의 경우 스크롤 이벤트의 잦은 발생을 막기 위해 debounce 메소드만을 사용하고 있었는데 엄청 아까운 용량이였다.
라이브러리의 필요한 부분만 남기기위한 기능이 존재하겠지라는 생각으로 구글링을 해보니 웹팩에서 사용하지 않는 코드를 제거해주는 Tree Shaking 기능이 있었다.
나무흔들기?
나무를 흔들어 죽은 잎을 떨어뜨리 듯 빌드 시에 사용하지 않는 코드를 제거하는 최적화 과정을 뜻한다.
Webpack의 공식 문서에 따르면 webpack2에서 사용하지 않는 모듈의 export를 감지하는 기능이 제공되고 webpack4에서 사이드이펙트에 관한 기능이 확장되며 보다 적합한 최적화가 가능해진 것으로 보인다.
( TMI. 현재 프로젝트는 webpack5를 사용 중이다. )
웹팩 공식 문서의 예시를 보니 named export 여야 하고 package.json의 "sideEffects" 에 추가되지 않은 파일이면 빌드 시 자동으로 최적화를 해주는 듯해 보였다.
(defalut export 경우도 가능하나 sideEffect 관련 설정을 해야 함)
그래서 lodash의 debounce 메서드를 사용한 코드를 확인해 보았다.
응? 지금도 뽑아썼는데?????
Tree Shaking이 작동되지 않는 대표적인 예시로 lodash 가 많이 사용되고 있었다.
import 해서 사용하는 해당 모듈의 export가 ES2015(export)로 내보내지고 있지 않기 때문이다.
lodash_github에서 UMD module로 export 하고 있음을 알 수 있었다.
그럼 ES 모듈로 내보내지 않은 모듈은 방법이 없나 해서 찾아보니
webpack-common-shake 플러그인을 추가하는 방법과
import 시에 모듈에서 메서드까지 한 번에 import? 하는 방법이 있었다.
후자의 방법으로 코드를 변경 후 다시 용량 테스트해보자!
Before & After의 차이가 엄청나다. 제대로 Tree Shacking이 동작함을 알 수 있었다.
lodash 라이브러리의 경우 ES모듈로 export한 lodash-es 라이브러리가 있고
lodash_github에서 권장하기에 lodash-es 라이브러리로 최종 수정을 했다.
https://ui.toast.com/weekly-pick/ko_20180716
https://webpack.kr/guides/tree-shaking/