웹사이트의 성능은 여러 가지 요소를 이용해 평가할 수 있습니다. 웹사이트의 성능을 개선하기 위한 한 가지 방법으로는 HTML이나 JavaScript 파일의 크기를 줄여 전송 시간을 줄이는 것입니다. 파일의 크기가 작을 수록 파일을 빨리 받아오니 로딩 속도가 빨라지겠죠?


실제로 이번에 진행한 프로젝트의 경우 몇몇 라이브러리들로 인해 크기가 상당히 커지게 되었습니다.

vite를 이용해 build를 진행하면 코드의 크기가 나오게 되는데, 위의 사진과 같이 2,255.79 kb나 되는 JavaScript 파일로 빌드된 것을 알 수 있죠.

코드 스플리팅

SPA의 단점 중 하나는 초기 로딩 시간이 길다는 것입니다. SPA는 하나의 페이지로 구성된 웹 애플리케이션이기 때문에 첫 로딩 시에 페이지에서 사용하는 모든 파일을 서버로부터 다운로드받아야 합니다. 그리고 이런 파일들의 총 크기는 당연히 커질 수 밖에 없겠죠. 하지만 여러 SPA 프레임워크, 라이브러리에서는 이를 개선하기 위한 방법을 제공하고 있습니다.

 

React에서는 Lazy와 Suspense를 이용하여 첫 로딩에 필요하지 않는 컴포넌트를 나중에, 필요한 순간에 가져올 수 있도록 만들어 줄 수 있습니다. 사용법만 간단하게 소개하기 위한 다음의 코드를 보시죠.

import { Suspense, lazy } from "react";
const ArticleEditor = lazy(
  () => import("./HeavyComponent")
);

const myComponent = () => {
    return (
        <>
            <Suspense fallback={<LoadingIndicator />}>
                  <HeavyComponent />
            </Suspense>
        </>
    )
}

같은 폴더의 Editor라는 컴포넌트를 하위 컴포넌트를 사용하는 myComponent입니다. React에서 기본으로 제공하는 Lazy는 HeavyComponent를 곧 바로 import하지 않겠다는 의미라고 생각하지면 됩니다. 대신 HeavyComponent가 사용되어야 할 순간에 서버에서 받아오게되죠. Suspense의 fallback은 HeavyComponent를 서버에서 받아오는 동안 대신 표시할 컴포넌트를 넣게 됩니다. lazy로 import할 컴포넌트는 무조건 Suspense 컴포넌트로 감싸주어 React가 아직 클라이언트 측에 존재하지 않는 Component를 가져오는 시도를 하지 않도록 해주어야 합니다.

 

이렇게 코드 스플리팅을 적용한 뒤의 결과는 다음과 같았습니다.

이미 분리가 되어 있었던 ArticleEditor와 BroadcastPage 컴포넌트는 너무 큰 파일을 제외하면 남은 두 개의 컴포넌트는 여전히 커다란 용량을 자랑하고 있습니다. 하지만 용량의 오른쪽을 보면 "gzip: 파일크기"라고 적힌 부분이 보일 것입니다. vite에서 gzip압축이 가능한 경우 압축 후의 에상 크기를 표시해 주고 있는 것입니다.

압축하기

gzip

HTTP 응답으로 보낼 파일을 압축하는 방법입니다. 위의 사진에서 보셨겠지만 파일의 크기를 코드 스플리팅보다 더 많이 줄여줄 수 있어 보입니다. 실제로 코드 스플리팅은 파일의 크기를 줄인다기 보다는 첫 로딩 시에 필요한 파일만 보내주겠다는 성격이 더 강합니다. 압축은 실제로 전체 파일의 크기가 줄어드는 효과를 볼 수 있죠. 파일을 전송하고, 받는 과정에서 압축과 압축 해체의 과정이 추가로 필요하지만, 현대의 컴퓨터나 모바일 기기들에게 부담이 되는 정도는 아니기 때문에 압축을 하는 것이 같은 요청 수에 대한 트래픽을 줄이고, 전송 속도가 더 빨라지기 때문에 전체 성능에 더 긍정적인 영향을 줄 수 있습니다. 특히, 인터넷이 느릴수록 더 큰 효과를 얻을 수 있습니다.

 

저의 경우 Nginx를 사용하여 프로젝트를 배포하였기 때문에 nginX를 기준으로 설명드리겠습니다. Nginx는 기본적으로 gzip을 지원하기 때문에, nginx.conf 파일에 다음과 같은 코드를 추가하면 되는 아주 간단한 작업입니다.

gzip on;
gzip_disable "msie6";

gzip_min_length  10240;
gzip_buffers 16 8k;
gzip_comp_level 9;
gzip_types
    text/plain
    text/css
     text/javascript
    application/javascript
    application/x-javascript
    text/xml text/css
    application/json;
    font/eot
    font/otf
    font/ttf
gzip_vary on;

해당 코드를 적용하고 배포한 웹 사이트에 접속하여 개발자 도구의 Network 탭을 확인하여 gzip 압축이 적용되었는지 확인 할 수 있습니다.

네이버의 gzip 압축된 css 코드

brotli

gzip 압축 외에도 brotli라는 압축 방법도 존재합니다. brotli가 gzip에 비해 더 높은 압축률을 가지고 있습니다. 그래서 파일의 크기를 더 줄일 수 있지만 압축과 해제 과정에 더 많은 시간이 소요되기 때문에 용량이 작은 파일들을 사용할 때에는 gzip보다 로딩 속도가 더 느려집니다. 해당 압축을 NginX에 적용하는 방법은 다음과 같습니다.

먼저 apt-get을 사용하여 모듈을 설치합니다.

sudo apt-add-repository -y ppa:hda-me/nginx-stable
sudo apt-get update
sudo apt-get install brotli nginx-module-brotli

이후, gzip 때와 마찬가지로 nginx.conf 파일에 다음 명령을 입력합니다.

load_module modules/ngx_http_brotli-filter-module.so;
load_module modules/ngx_http_brotli-static-module.so;

http {
    brotli_static on;
    brotli_types text.plain text/css applications/javascript applications/x-javascript text/xml apllication/xml+rss text/javascript image/x-icon image/vnd.microsoft.icon image/bmp image/svg+xml;
}

gzip과 마찬가지로 brotli가 정상적으로 적용되었다면 응답 헤더에 Content-Encoding: br를 볼 수 있습니다.

같은 프로젝트를 brotli 알고리즘을 통해 압축을 하게 된다면 gzip보다 더 큰 압축률을 볼 수 있습니다.

vite-plugin-compression2를 이용해 brotli 압축을 시행한 결과

브라우저 지원 여부

brotli가 gzip에 비해 지원하는 브라우저가 적은 것으로 알려져 있어 직접 can i use를 이용해 지원여부를 조사한 결과 지원하는 브라우저는 다음과 같습니다. - gzip이나 brotli나 지원하는 브라우저의 목록은 같아보입니다.

gzip

gzip 브라우저 지원 여부, 출처: can i use?

Brotli

brotli 브라우저 지원 여부, 출처: can i use?

참고 자료

Nginx, Compression and Decompression

Containerize, nginx에서 gzip 압축을 사용하여 웹 사이트 최적화 방법

요즘 IT, Brotli 압축 알고리즘으로 웹사이트 속도 올리기

+ Recent posts