회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
우리가 사용하는 웹사이트는 웹 페이지의 크기가 크면 클수록 로딩 속도가 느려집니다. 로딩 속도가 느려지면 이용자가 서비스를 이탈할 확률이 높아지기 때문에 로딩 속도는 서비스를 제공하는데 매우 중요한 요소입니다. 로딩속도를 빠르게 하기 위해서 여러 방법이 존재하는데, 그중 하나가 파일 압축을 통해 전송되는 웹 페이지 파일의 크기 자체를 줄이는 방법입니다. 이번 글에서는 Brotli 압축 알고리즘으로 파일 크기 줄이는 방법을 알아보겠습니다.
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
우리가 사용하는 웹사이트는 웹 페이지의 크기가 크면 클수록 로딩 속도가 느려집니다. 로딩 속도가 느려지면 이용자가 서비스를 이탈할 확률이 높아지기 때문에 로딩 속도는 서비스를 제공하는데 매우 중요한 요소입니다. 로딩속도를 빠르게 하기 위해서 여러 방법이 존재하는데, 그중 하나가 파일 압축을 통해 전송되는 웹 페이지 파일의 크기 자체를 줄이는 방법입니다. 이번 글에서는 Brotli 압축 알고리즘으로 파일 크기 줄이는 방법을 알아보겠습니다.
HTTP 압축은 앞서 말했듯 전송되는 웹페이지 파일 자체를 압축 알고리즘을 통해 압축하여 사용자에게 제공하는 방법으로, 현재 출시된 대부분의 브라우저에서 기본적으로 HTTP 압축을 지원합니다.
우리가 주소창에 주소를 입력하여 웹사이트에 접속하면 일반적으로 다음과 같은 과정을 거칩니다.
※ 실제로는 훨씬 더 많은 단계가 존재하지만, 간단한 설명을 위해 생략하도록 하겠습니다.
종단간 HTTP 압축은 위와 같은 HTTP 통신에서 웹 서버가 웹 브라우저로 전송하는 파일을 압축하여 전송하는 방법입니다. HTTP 압축이 적용된 경우 2번 과정과 3번 과정 사이에 몇 가지 과정이 더 추가됩니다. 압축 알고리즘은 전통적으로 많이 쓰이는 gzip 압축 방식과 오늘 소개할 br 방식, 그리고 다른 여러 압축 방법이 존재하기 때문에 단순히 '압축된 파일을 전송해 주세요’라고 하는 것 만으로는 충분히 설명되지 않습니다.
그래서 웹 브라우저는 요청 패킷의 헤더에 웹 브라우저가 해석할 수 있는 인코딩 방법(어떤 알고리즘으로 압축된 파일을 인식할 수 있는지)을 명시하여 웹 서버에 파일을 요청합니다. 웹 서버는 요청 패킷의 헤더를 읽고 어떤 알고리즘을 통해 파일을 압축하여 전달할지 결정하고, 압축한 알고리즘의 종류를 응답 패킷의 헤더에 명시한 뒤 응답 패킷의 바디에 압축한 파일을 담아 웹 브라우저로 전달합니다.
위의 내용을 바탕으로 전체적인 과정을 다시 살펴보면 다음과 같습니다.
Deflate 알고리즘은 ZIP 포맷에 사용하기 위해 만들어진 압축 알고리즘으로 LZ77 압축 알고리즘과 Huffman 코딩 알고리즘의 결합으로 이루어져 있습니다.
LZ77 압축 알고리즘은 1977년 Abraham Lempel과 Jacob Ziv가 개발한 기술로, 문자열을 입력 받아 해당 문자열에서 중복된 문자열을 찾아낸 다음, 이를 LLD 토큰(distance, length, literal)으로 변경하여 입력된 문자열을 압축하는 방식입니다. 예를 들어 문자열 ‘abcdeabcdf’를 LZ77로 압축하면 abcd라는 문자열이 중복되므로 abcde(5, 4, ’f’)와 같은 문자열로 압축합니다.
요약하자면 LZ77 알고리즘은 반복적으로 나오는 문자열을 압축하는 사전 방식 알고리즘으로, 문자열을 LLD 토큰들로 변환하는 알고리즘이라는 정도로 이해하면 쉽습니다.
허프만(Huffman) 코딩 또한 다른 무손실 압축 알고리즘으로, 1950년 David Huffman이 개발했으며 JPEG와 같은 여러 가지 압축 알고리즘에 사용됩니다. 허프만 코딩은 문자의 빈도를 바탕으로 파일을 분석합니다. 이때 해당 문자열이 등장하는 빈도가 낮으면 긴 길이의 부호를, 빈도가 높으면 짧은 길이의 부호를 부여하는 접두사 인코딩 방식입니다.
허프만 코딩을 진행하기 위해서는 전체 원문에서 각 토큰 또는 문자열의 출현 빈도를 파악한 뒤 이를 바탕으로 이진 트리를 작성하여 이진 트리를 순회하면서 출현 빈도가 높은 토큰 또는 문자열부터 짧은 부호를 부여합니다.
만약 A가 45%, C가 18%, D가 27%, E가 9% 등장하는 원문이라면, 출현 빈도 순서는 A, D, C, E이므로 빈도가 낮은 A부터 길이가 짧은 부호를 부여하여 A - 0, D - 10, C - 111, E - 110과 같이 부호를 부여하여 압축된 텍스트가 가장 짧은 길이를 가질 수 있도록 합니다.
Deflate 알고리즘은 앞서 간단히 설명한 LZ77과 Huffman 코딩을 모두 사용합니다. LZ77을 거쳐 나온 LLD 토큰들을 Huffman 코딩을 이용해 이진값으로 변환하는 과정을 거쳐 압축을 진행합니다. 해당 과정의 구현체인 zlib은 압축률에 비해 속도가 매우 빠른 편이기 때문에 여러 CDN 또는 웹 서버에서 주로 사용되고 있습니다.
브로틀리(Brotli) 알고리즘은 Deflate의 구현체인 zlib을 개선하여 zopfli 라이브러리를 만든 뒤 해당 라이브러리를 만들며 적용했던 몇 가지 방법을 본격적으로 활용한 방식입니다. 쉽게 요약하면, Brotli는 LZ77 알고리즘과 Huffman 코딩, 그리고 더 나아가 고정된 크기의 키워드 사전과 필요 시 가변 크기의 키워드 사전을 제작하여 사용하도록 인코더를 개발하였습니다.
고정된 크기의 키워드 사전에는 javascript, html, css 등 여러 가지 웹 환경에서 사용되는 명령어(예: html 태그, javascript 예약어 등)를 모아둔 데이터들이 120KB 정도로 담겨있습니다. 가령 태그의 경우 파일에서 단 한 번씩만 등장하기 때문에 gzip에서는압축되지 않지만, Brotli의 고정 크기 사전에는 등록되어 있으므로 압축할 수 있습니다.
사실 gzip의 가변 크기 사전이 대부분 10KB를 넘지 않기 때문에 사전 크기에서 큰 차이가 있습니다. 하지만 키워드 사전의 용량이 크더라도 해당 사전은 HTTP 통신으로 전달하는 것이 아니라 이미 웹 브라우저가 내장하고 있으므로 파일 로딩 시간에 거의 영향을 미치지 않습니다.
해외 분석 글에 따르면, Brotli 알고리즘 압축이 gzi보다 압축률이 높은 걸 확인할 수 있습니다. 그래서 html 페이지와 같이 용량이 큰 정적 콘텐츠는 전체적인 로딩 속도에서 이득을 얻을 수 있습니다. 하지만 압축 해제 속도와 압축 속도는 gzip보다 훨씬 느리기 때문에 용량이 작은 동적 콘텐츠를 주고받을 때는 gzip 압축보다 로딩 속도가 느린 편입니다.
만약 Brotli를 사용할 수 있는 환경이라면 웹 브라우저가 요청 패킷의 헤더에 Accept-Encoding: br
를 붙여서 전달합니다. 웹 서버는 브라우저의 요청에서 Accept-Encoding 헤더를 읽고 br이 들어있으면 Brotli 방식으로 내용을 압축하여 전달하도록 만들면 됩니다. 이때 이미 압축된 jpeg나 png 등의 파일은 별도로 압축하는 일이 없도록 하여야 합니다.
Apache2
가상 호스트 설정 파일에 아래와 같이 내용을 추가합니다.
※ Apache 문서 참고
<IfModule mod_brotli.c>
SetOutputFilter BROTLI_COMPRESS
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-brotli
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/javascript
</IfModule>
Apache Brotli 모듈을 활성화한 후 서버를 재시작합니다.
sudo a2enmod brotli
sudo systemctl restart apache2
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
/etc/nginx/nginx.conf
파일을 열고 상단에 아래와 같이 Brotli 관련 모듈 로드 명령을 입력합니다.
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
이후 http { }
구문 사이에 아래와 같이 Brotli 관련 설정을 추가합니다.
http{
brotli_static on;
brotli_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/x-icon image/vnd.microsoft.icon image/bmp image/svg+xml;
}
적용한 br 알고리즘이 서버에 제대로 적용되었는지 테스트하기 위해서는 아래와 같이 Accept-Encoding 헤더의 값으로 'br’를 담아 전송하면 확인할 수 있습니다.
curl -IL https://yozm.wishiket.com -H "Accept-Encoding: br"
돌아오는 응답의 header에 content-encoding: br
이 붙어서 온다면 제대로 적용된 것입니다.
Brotli 알고리즘은 정적인 파일만 보았을 때 gzip에 비해 압축 속도도 빠르고 압축률도 높아서 웹 사이트의 속도 향상을 기대할 수 있습니다. 그렇지만 동적 파일에 대해서는 gzip에 비해 그렇게 큰 성능 향상을 기대하기 어렵습니다. 또한 익스플로러에서 작동하지 않는 건 둘째치더라도, 브라우저 점유율이 높은 모바일 iOS 사파리에서 아직까지 지원하지 않기 때문에 선택을 망설이게 됩니다.
다만 웹사이트에서 Brotli 지원 자체는 그렇게 큰 비용이 소모되지 않는 일이고, 인터넷이 느린 환경이나 요금이 비싼 국가 등의 환경에서는 큰 도움이 될 수 있기 때문에 여유가 있으면 일단 사이트에 적용해도 나쁘지 않으니 한 번쯤 고려해 보시기 바랍니다.
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.