네이버 부스트캠프 8기 그룹 프로젝트로 AlgoITNi라는 프로젝트를 진행했다.
동료들과 함께 소통하며 알고리즘 학습을 할 수 있는 플랫폼을 만들고자 했으며 이를 위해
등의 기능을 구현하게 되었다.
이 과정에서 다양한 시도들이 있었으며 그 중 하나인 홈 화면 성능 개선하기에 대해 정리해본다.
홈 화면 성능을 개선하기로 한 이유는 단순하지면 명확하다.
홈 화면은 사용자가 우리 서비스에 접근할 때 가장 먼저 접근하는 곳이기 때문이다.
홈 화면에서 빠른 응답 속도를 통해 좋은 UX를 제공한다면 사용자의 입장에서 우리 서비스를 긍정적으로 생각할 수 있기 때문이다.
또한, 대부분의 로직은 Room 안에 있기 때문에 불필요한 코드는 Home에 필요가 없었다.
성능 분석 및 최적화에 관심이 있었기 때문에 이번에 새롭게 배운 내용들을 적용해보고 싶었다.
(개발환경 Lighthouse)
첫 시작은 빌드 과정에서 위와 같은 경고로부터 시작한다.
위의 경고를 해석해보면 단일 청크의 크기가 500KB를 초과한다는 내용이다.
이를 위해서 동적 import를 통한 코드 스플리팅 또는 rollupOptions
를 이용해 limit를 높이는 것을 제안하고 있다.
(rollupOptions
를 수정하라는 추천도 있지만 단순히 경고 기준인 500KB를 1MB로 증가시키는 등의 방법이기 때문에 실질적인 도움이 되지않는다고 판단했다)
우선 빌드 결과물이 왜 이렇게 커졌는지 분석하기 위해 Vite 번들 분석 도구를 활용해야 한다.
npx vite-bundle-visualizer
번들링 크기를 확인해보면 코드 하이라이팅을 위한 highlight.js
라이브러리가 번들링 크기의 50% 이상을 차지하고 있음을 알 수 있다.
그 이유는 highlight.js
에서는 많은 언어를 지원하기 때문에 우리가 사용하지 않는 언어에 대한 정보도 함께 번들 과정에 포함되기 때문이다.
기존 코드는 아래와 같다.
import hljs from 'highlight.js';
const highlightCode = (language: string, code: string) => {
return hljs.highlight(code, { language }).value.replace(/" "/g, ' ');
};
export default highlightCode;
highlight.js 전체를 import 하여 사용하고 있는 것을 볼 수 있다.
이를 해결하기 위해 현재 서비스에서 사용하는 언어만 import 하도록 수정해야 한다.
단, 향후 서비스에서 어떤 언어를 지원할지 모르기 때문에 config 파일을 생성하여 import를 관리할 수 있도록 했다.
트리 쉐이킹을 통해 필요한 언어 정보만 가져오되 추후 언어 추가에 유연하게 대응하기 위함이었다.
import codeHighlighter from 'highlight.js/lib/core';
import python from 'highlight.js/lib/languages/python';
import javascript from 'highlight.js/lib/languages/javascript';
codeHighlighter.registerLanguage('python', python);
codeHighlighter.registerLanguage('javascript', javascript);
export default codeHighlighter;
import codeHighlighter from "@/configs/highlightCodeConfig";
const highlightCode = (language: string, code: string) => {
return codeHighlighter.highlight(code, { language }).value.replace(/" "/g, ' ');
};
export default highlightCode;
위와 같이 서비스에서 실제로 사용하는 언어만 import 할 수 있도록 수정했다.
만약, 새로운 언어가 추가된다면 import만 하나 추가해준다면 해당 언어도 적용할 수 있다.
결과적으로 highlight.js
의 불필요한 부분을 제거할 수 있었고 다음과 같은 결과를 얻을 수 있었다.
전역 상태 관리 라이브러리를 선택하는 과정에서도 번들링 크기를 고려하게 되었다.
종류 | recoil | zustand |
---|---|---|
번들 크기 | 2.17MB | 187KB |
상태관리 방식 | 상태 위주의 관리 | 상태와 상태를 변경하는 함수를 따로 작성하여 관리 |
추후 상태를 변경하는 action이 많아지면 recoil 역시 custom hook을 자주 사용하게 되므로, 번들 크기가 작고 상태와 상태변경 함수가 분리된 zustand를 사용하게 되었다.