최근 NPM 모듈을 사용한 Webpack 개발을 시작했다. Webpack은 기존 여러 파일을 불러오는 것보다 효율적으로 네트워크 전송을 구현할하도록 도와준다. Tree shaking 기능을 활용해 불필요한 코드를 제거하는 일도 가능했다. 하지만 필요한 모듈만 불러왔을 뿐인데 용량은 250KB로 컸다. 구글에서 제안하는 크기는 170KB. 많은 부분에서 수정이 필요했다.

먼저 번들 안에 어떤 모듈들이 차지하고 있는지 판단해야했다. webpack-bundle-analyzer 플러그인은 코드 내 차지하고 있는 각 모듈의 비율을 다이어그램으로 표현한다. 아주 작은 모듈로까지 확대할 수 있어 불필요한 코드를 판단하는 데 최적이었다.

jQuery

플러그인으로 번들을 분석하니 가장 눈에 띄는 것이 jQuery였다. DOM 작업을 위해서 자주 사용해왔다. 하지만 80KB나 손해볼 정도로 꼭 필요한 것은 아니었다.

먼저 element를 가져오기 위해 사용했던 $('#test') 등을 document.querySelector('#test')로 변경했다. 작업하면서 다소 주의해야할 부분이 있다면 document.querySelectorAll()을 사용할 경우 classList를 바로 사용할 수 없다는 것이다.1

사실 그 다음이 문제였다. AJAX. 예전부터 AJAX 송신을 위해선 jQuery를 사용했다. 하지만 AJAX가 XMLHttpRequest의 Wrapper임을 생각했을 때 불필요한 것이었다. 따라서 순수 자바스크립트로 다시 짤 수 있었다.

작업을 하면서 가장 골머리를 앓았던 부분은 Submit을 하면 자동으로 action 주소로 넘어가는 것이었다. XHR 구현에서 가장 중요한 부분이 타 페이지로 넘어가지 않는 것이었기 때문에 곤란했다. 이 문제는 이벤트 리스너에 event 인자를 받아서 event.preventDefault() 메서드를 추가해 해결할 수 있었다.

한가지 더 문제는 폼 데이터를 전송하는 방법이었다. jQuery에서는 폼 데이터를 받을 때 serialize() 라는 메서드를 사용하여 Object형식으로 데이터를 보낼 수 있었다. 다행히 Native API에서도 비슷한 역할의 FormData 함수를 지원하여 대체할 수 있었다. 아쉬운 것은 Safari는 여전히 FormData의 entries() 메서드 등을 지원하지 않아 Polyfill2을 써야한다는 정도. 이렇게 jQuery의 의존성을 제거하였다.

Algolia

다음으로 문제가 된 것이 Algoliasearch의 모듈 사이즈였다. 이 문제는 생각보다 쉽게 해결하였다. Algolia에서 제공하는 lite 버전을 불러오는 것으로 용량을 대폭 줄일 수 있었다. Algoliasearch-helper 모듈도 가벼운 버전이 있지 않을까 찾아봤지만 아쉽게도 발견하지 못했다.

lodash

마지막으로 lodash. 직접 코드를 짜면서 lodash를 쓰진 않았지만 Algolia의 의존성 때문에 자동으로 불러와졌다. lodash는 일부 코드만 모듈로 불러오더라도 생각보다 큰 용량을 가져오기 때문에 최적화가 필요했다. 이 문제는 lodash-webpack-plugin으로 해결했다. 작업을 하면서 다소 주의했던 점은 lodash-webpack-plugin을 사용하면 자동으로 shorthands 함수가 제거되기 때문에 추가적으로 설정할 필요가 있었다는 점이었다.

여러 과정을 거치면서 내 번들사이즈는 250KB에서 150KB까지 줄일 수 있었다. 다만 아쉬운 점은 FormData를 Polyfill로 정의했다는 점과 Algoliasearch-helper 모듈의 큰 용량을 줄이지 못했다는 것이었다. 해당 모듈 역시 일부만 불러올 수 있을 것 같아 생각을 더 해봐야겠다.