이전에 진행했던 프로젝트를 다시 실행해봤는데 화면이 나타날 때까지의 시간이 오래 걸리는 것을 보고 성능 개선을 해봐야겠다는 생각이 들었다. 제일 먼저 간단하게 Lighthouse를 사용하여 화면의 성능을 측정해 보았다.
Lighthouse란?
Lighthouse는 구글에서 만들 틀로, 웹사이트의 성능을 측정하고 개선 방향을 제시해 주는 자동화 틀이다. Lighthouse를 이용하면 웹사이트의 성능 점수를 측정하고 개선 가이드를 확인함으로써 어떤 부분을 중점적으로 최적화해야 하는지에 대해 알 수 있다.
Performance 점수가 36점… 왜 이렇게 낮을까?
개선해야 할 점을 보면 사용하지 않은 자바스크립트의 파일을 줄이라고 나와있다. 그리고 가장 위의 용량이 큰 파일을 보면 bundle.js라고 되어 있는데 이건 뭘까?
Bundle?
번들링이란 사용자에게 웹 어플리케이션을 제공하기 위해 여러 코드와 프로그램을 묶는 것을 말한다. 개발자는 최종적으로 번들링된 웹 어플리케이션을 만들고, 사용자가 웹 어프리케이션을 이용할 때는 번들링한 파일을 서버로부터 받아서 브라우저가 이 번들을 실행한다.
create-react-app으로 시작하는 경우, 기본적으로 Webpack 및 Babel이 설정 되어 있는데 번들링을 하게 되면 모든 자바스크립트 파일이 하나의 자바스크립트 파일(bundle.js)로 합쳐지게 된다. 번들된 파일은 프로젝트의 크기가 커질 수록 용량이 커지며, 처음 페이지에 접근할 때 자바스크립트의 파일을 불러오는 Client-Server-Landering의 특성 상 시간이 오래 걸리는 문제가 발생할 수 있다.
React 공식 홈페이지에서는 이러한 문제를 개선할 수 있는 방법으로 코드 분할(Code Splitting)을 제시하고 있다.
코드분할(Code Splitting)
코드분할을 이용하면 페이지별로 코드를 분할하는 것으로 하나의 번들 파일을 여러 개의 파일로 쪼개는 방법이다. 분할된 코드는 사용자가 서비스를 이용하는 중에 해당 코드가 필요해지는 시점에 로드되어 실행되는데, 이를 지연 로딩이라고 한다. (필요 없는 코드를 다운로드 하지 않으니 로드 속도는 빨라지게 된다.)
lazy와 Suspense 함수를 사용하여 동적 import를 할 수 있다.
Before
import OtherComponent from './OtherComponent';
After
const OtherComponent = React.lazy(() => import('./OtherComponent'));
lazy 컴포넌트는 Suspense 컴포넌트 하위에 렌더링되어야 하며, Suspense는 lazy 컴포넌트가 로드 되기를 기다리는 동안 로딩 화면과 같은 컨테츠를 보여줄 수 있다.
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
이렇게 해서 코드 분할을 진행해보니 번들 사이즈가 거의 절반으로 줄어든 것을 볼 수 있었다.
react-icons
아이콘을 사용하기 위해서 react-icons라는 라이브러리를 사용하였는데, 사용한 아이콘의 수 보다 라이브러리의 chunck 사이즈가 크다는 것을 알 수 있었다.
react-icons는 아이콘의 종류별로 구분되어 있고 종류별로 하나의 js 파일에 아이콘 전체를 포함하고 있는데, 이 때문에 아이콘 하나만 가져오려고 해도 해당 아이콘을 담고 있는 전체 파일을 사용하기 때문에 성능 문제가 발생하게 된다.
그래서 찾아보니 react-icons에서 @react-icons/all-files
라는 별도의 라이브러릴 제공하는데, 해당 라이브러리는 아이콘 별로 자바스크립트 파일을 별도로 가지고 있어 빌드 시 트리 쉐이킹 방식으로 더 적은 크기의 chunk를 만들 수 있다고 한다.
Before
import { FaBeer } from "react-icons/fa";
After
import { FaBeer } from "@react-icons/all-files/fa/FaBeer";
👍🏻 성능 개선 결과
기존 36점이였던 Performance 점수가 50점으로 상승한 것을 볼 수 있었다.
아직까지 낮은 점수를 가지고 있는데 나머지 문제점도 해결해봐야겠다.🥲
참고
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=304371832
'개발이야기' 카테고리의 다른 글
Refresh token을 활용하여 Access token 갱신하기 (0) | 2023.09.05 |
---|---|
Lighthouse를 이용한 성능 개선 - 이미지 최적화 (0) | 2023.04.14 |