이번에는 쇼핑몰 전반 콘텐츠를 압축해 속도를 높여주는 압축 프로그램도 보다 보안이 뛰어난 프로그램인 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법에 대해서 살펴 봅니다.
보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법
쇼핑몰 구축기를 연재하는 이유
최근 지인이 워드프레스를 이용해 쇼핑몰 구축을 시도하면서 배웠던 배웠던 다양한 경험들을 해당 쇼핑몰 블로그에 연재해 왔는데요.
쇼핑몰이 상품만 파는 것이 아니라 쇼핑몰을 방문하는 고객들에게 열가지 유용한 정보를 제공하는 블로그의 효용성이 높다는 점을 십분 활용하고, 처음 시작하는 쇼핑몰의 신뢰성을 주기 위해 비록 삽질이지만 삽질기를 낱낱히 공개하기로 했다고 하네요.
그 쇼핑몰의 주소는 https://puripia.com로 아직도 공사중이기는 합니다.)
쇼핑몰 구축 시 도와주었던 인연으로 그 쇼핑몰을 알리고 쇼핑몰 구축 경험담을 보다 널리 알리기 위해서 여기 happist.com에도 같이 공유합니다. 조금 사심이 있기는 합니다.
보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법
여기에서는 보안과 속도 측면에서 좋은 평가를 받고 있는 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법에 대해서 알아 봅니다.
보안과 속도는 상당히 양립하기 어려운 문제죠. 보안을 강화하면서도 속도를 높인다는 것은 쉽지않은 문제이기 때문이죠.
그렇지만 주제가 속도를 빠르게 해주는 솔류션의 문제라면 다르겠죠. 속도를 높여주는 솔류션이 보안과 연계되어 보안을 높이는 요인이 있다면 금상첨화겠죠.
오늘 이야기하려는 브로틀리 압축((Brotli Compression)이 그러한 한 예가 되지않을까 싶습니다.
1. 가장 널리 사용되는 gzip
그동안 서버에서 제반 포맷들을 압축해주는 솔류션으로 gzip이 널리 사용되었습니다.
이 gzip은 대부분의 웹서버가 기본으로 제공하는 기능으로 별다른 조치없이도 적용 옵션만 제대로 명기해 주는 것으로 작동했습니다.
그만큼 안정적이고 적용하기도 어렵지 않았다는 반증이기도 합니다.
그러나 이 gzip은 보안 측면에서는 완벽하지않다는 평가를 받고 있으며, 가능하면 브로틀리 압축((Brotli Compression)으로 대체하라는 주문이 있기도 합니다.
이전에 소개한 “SSL 보안 등급 A+에 도전하는 Let’s Encrypt 인증서 세팅 방법”에서도 잠깐 언급되었던 내용이기도 합니다.
2. 2016년부터 확산되기 시작한 브로틀리 압축((Brotli Compression)
그러는 가운데 구글은 브로틀리 압축((Brotli Compression) 기술을 오픈 소스로 공개했습니다.
그리고 가장 많은 점유율을 가진 크롬이 2016년 5월 27일부터 브로틀리 압축((Brotli Compression)을 지원하기 시작하면서 본격적으로 확산되기 시작했습니다.
지금은 화이어폭스, 마이크로소프트 Edge, 사파리 등 대부분의 주요 브라우져가 이를 지원하고 있습니다. 우리나라에서 아직도 많이 사용하는 IE는 아직 지원하지 않고 있네요.
![[쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 1 [쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 1](https://puripia.com/wp-content/uploads/2019/05/브로틀리-압축Brotli-Compression을-지원하는-브라우저-약-90-커버리지라고-밝히고-있다-1024x464.jpg)
3. Gzip vs 브로틀리 압축((Brotli Compression)
당연하게도 기존에 널리 사용되었던 gzip과 브로틀리 압축((Brotli Compression) 간의 비교가 관심이 많을 것으로 보입니다.
안전성 여부를 떠나서 압춧 성능과 관련해 비교해 놓은 자료들이 많은데요.
“Text Compression in R: brotli, gzip, xz and bz2 “ 라는 글에서 gzip과 brotli 등 여러 압축 기술들을 평가해 놓은 글을 참조해 봤습니다.
이에 따르면 압축율은 브로틀리 압축((Brotli Compression)이 가장 뛰어납니다.
![[쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 2 [쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 2](https://puripia.com/wp-content/uploads/2019/05/image-1024x512.png)
그러나 압축 속도는 gzip이 브로틀리 압축((Brotli Compression) 보다도 훨씬 뛰어납니다.
![[쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 3 [쇼핑몰 구축기] 보안과 속도를 위해 브로틀리 압축((Brotli Compression)을 Nginx에서 쉽게 이용하는 방법 3](https://puripia.com/wp-content/uploads/2019/05/image-1-1024x512.png)
여기에서 테스트한 결과를 토대로 정적인 파일(static contents)에는 브로틀리 압축((Brotli Compression)이 뛰어나지만 동적 콘텐츠( on-the-fly)나 스트리밍 데이타에는 적합하지 않다는 평가를 내리고 있습니다.
3. Nginx에서 브로틀리 압축((Brotli Compression) 적용 어려움
종종 언급하지만 nginx는 상당히 장점이 많은 웹서버이지만 때로는 불리한 점도 있습니다.
예를 들어 브로틀리 압축((Brotli Compression)과 같이 새로운 기술의 경우 nginx용으로 개발되어 자동으로 적용되지 않고 별도로 ngix에 맞추어 컴파일을 해줘야 합니다.
이는 nginx 버젼이 바뀌면 이에 맞추어 다시 컴파일해서 세팅해야 한다는 것을 의미합니다. 관리하기 쉽지가 않다는 것이죠.
아래와 같은 글에서 버젼이 바뀌어도 브로틀리 압축((Brotli Compression)을 계속 적용할 수 있다고 하지만 이는 잘 작동하지 않습니다.
아래 글에서 소개하는 방법도 nginx 버젼이 높아지면 별도로 컴파일하는 절차를 다시 진행해야 합니다.
[사이트 속도 개선] 브로틀리 압축(Brotli Compression)으로 속도를 개선해 보기
4. 명령어 하나로 브로틀리 압축((Brotli Compression) 적용하고 데이트하기
그냥 nginx가 업데이트되면 자동으로 브로틀리 압축((Brotli Compression)도 업데이트되면 가장 좋겠지만 이게 가능하지 않으므로 차선으로 쉬운 방법을 찾아 보았습니다.
안벽하지는 않지만 아주 쉽게 자동화할 수 있는 방법이 인터넷에 소개되어 있습니다. 아래 링크를 참조..
Compile Nginx from Source with Brotli Support
여기서 소개하고 있는 brotli.sh 파일을 서버 root에 설치하고 bash 명령어로 실행 시키면 됩니다.
4.1. brotli.sh 만들기
아래처럼 nano와 같은 편집기 명령어를 이용해 brotli.sh 파일을 만듭니다.
nano brotli.shCode language: PHP (php)
이 파일에는 아래 내용을 추가합니다.
#!/usr/bin/env bash
# version 1.2
# use it while developing / testing.
# you may use it in production as well.
# set -o errexit -o pipefail -o noclobber -o nounset
# set -x
# compile Nginx from the official repo with brotli compression
[ ! -d ${HOME}/log ] && mkdir ${HOME}/log
G_DIR="$(pwd)"
# logging everything
log_file=${HOME}/log/brotli.log
exec > >(tee -a ${log_file} )
exec 2> >(tee -a ${log_file} >&2)
# Defining return code check function
check_result() {
if [ $1 -ne 0 ]; then
echo "Error: $2"
exit $1
fi
}
export DEBIAN_FRONTEND=noninteractive
printf '%-72s' "Updating apt repos..."
sudo apt-get -qq update
echo done.
printf '%-72s' "Installing pre-requisites..."
sudo apt-get -qq install dpkg-dev build-essential zlib1g-dev libpcre3 libpcre3-dev unzip
echo done.
codename=$(lsb_release -c -s)
# function to add the official Nginx.org repo
nginx_repo_add() {
distro=$(gawk -F= '/^ID=/{print $2}' /etc/os-release)
if [ "$codename" == "juno" ] ; then
codename=bionic
fi
if [ "$distro" == "elementary" ] ; then
distro=ubuntu
fi
if [ "$distro" == "linuxmint" ] ; then
distro=ubuntu
fi
[ -f nginx_signing.key ] && rm nginx_signing.key
curl -LSsO http://nginx.org/keys/nginx_signing.key
check_result $? 'Nginx key could not be downloaded!'
sudo apt-key add nginx_signing.key &> /dev/null
check_result $? 'Nginx key could not be added!'
rm nginx_signing.key
# for updated info, please see https://nginx.org/en/linux_packages.html#stable
nginx_branch= # leave this empty to install stable version
# or nginx_branch="mainline"
if [ "$nginx_branch" == 'mainline' ]; then
nginx_src_url="https://nginx.org/packages/mainline/${distro}/"
else
nginx_src_url="https://nginx.org/packages/${distro}/"
fi
[ -f /etc/apt/sources.list.d/nginx.list ] && sudo rm /etc/apt/sources.list.d/nginx.list
echo "deb ${nginx_src_url} ${codename} nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
echo "deb-src ${nginx_src_url} ${codename} nginx" | sudo tee -a /etc/apt/sources.list.d/nginx.list
# finally update the local apt cache
sudo apt-get update -qq
check_result $? 'Something went wrong while updating apt repos.'
}
case "$codename" in
"stretch")
nginx_repo_add
;;
"xenial")
nginx_repo_add
;;
"bionic")
nginx_repo_add
;;
"juno")
codename=bionic
nginx_repo_add
;;
"tara")
codename=bionic
nginx_repo_add
;;
*)
echo "Distro: $codename"
echo 'Warning: Could not figure out the distribution codename. Continuing to install Nginx from the OS.'
;;
esac
sudo install -o ${UID} -g $(id -gn $USER) -d /usr/local/src/${USER}
cd /usr/local/src/${USER}
apt-get source nginx
sudo apt-get build-dep nginx -y
git clone --recursive https://github.com/eustas/ngx_brotli
sudo ln -s /usr/local/src/${USER}/ngx_brotli /usr/local/src/ngx_brotli
sudo chown ${USER}:$USER:$(id -gn $USER) /usr/local/src/ngx_brotli
cd /usr/local/src/${USER}/nginx-*/
# modify the existing config
sed -i -e '/\.\/configure/ s:$: --add-module=/usr/local/src/ngx_brotli:' debian/rules
# if gcc 8 is installed add patch to nginx
if [ "$(gcc -dumpversion)" == "8" ]; then
mkdir -p debian/patches
cp ${G_DIR}/gcc-8_fix.diff debian/patches/gcc-8_fix
echo "gcc-8_fix" > debian/patches/series
fi
# build the updated pacakge
dpkg-buildpackage -b
# optional
# install the updated package in the current server
cd /usr/local/src/${USER}
# take a backup
[ ! -d ~/backups/ ] && mkdir ~/backups
cp nginx*.deb ~/backups/nginx-$(date +%F)/
# sudo apt-mark unhold nginx
sudo dpkg -i nginx_*.deb
# print info about remove all the sources and apt sources file
cd ~/
printf "
# To clean up after install You can run
rm -rf /usr/local/src/$(echo ${USER})/nginx*
rm -rf /usr/local/src/$(echo ${USER})/ngx_brotli
sudo rm /etc/apt/sources.list.d/nginx.list
sudo apt-get -qq update
"
# hold the package nginx from updating accidentally in the future by someone else!
sudo apt-mark hold nginx
# stop the previously running instance, if any
sudo nginx -t && sudo systemctl stop nginx
# start the new Nginx instance
sudo nginx -t && sudo systemctl start nginxCode language: PHP (php)
이렇게 만들어진 brotli.sh의 파일 권한을 변경합니다.
chmod +x brotli.shCode language: PHP (php)
이 파일을 아래와 같이 bash 명령을 사용해 실행합니다.
bash britli.shCode language: PHP (php)
그러면 설치 전과정을 알아서 진행합니다. nginx 버젼을 파악해서 말이죠.
nginx 버젼이 변경될때마다 위에서 소개한 bash brotli.sh 명령으로 자동으로 새로 업데이트된 ngix에 맞추어 브로틀리 압축((Brotli Compression)을 적용할 수 있습니다.


![[쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 4 HPKP(HTTP Public Key Pinning) 개념도, 이미지 출처 - keycdn.com](https://puripia.com/wp-content/uploads/2019/05/HPKPHTTP-Public-Key-Pinning-개념도-이미지-출처-keycdn.com_-1024x513.png)
![[쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 5 [쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 4](https://puripia.com/wp-content/uploads/2019/05/HPKPHTTP-Public-Key-Pinning를-뽑아주는-사이트-1024x376.png)
![[쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 6 [쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 5](https://puripia.com/wp-content/uploads/2019/05/HPKPHTTP-Public-Key-Pinning를-뽑아주는-사이트2-1024x731.jpg)
![[쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준 7 HPKP(HTTP Public Key Pinning) 적용 상태를 테스트한 결과](https://puripia.com/wp-content/uploads/2019/05/HPKPHTTP-Public-Key-Pinning-적용-상태를-테스트한-결과-1024x721.jpg)
![[쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 8 [쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 6](https://puripia.com/wp-content/uploads/2019/05/구글이-제시하는-HSTS-조건.png)
![[쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 9 [쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 7](https://puripia.com/wp-content/uploads/2019/05/구글-HSPT-등록-화면-987x1024.png)
![[쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 10 [쇼핑몰 구축기] HSTS로 보안과 속도 그리고 SEO까지 세마리 토끼를 잡자 8](https://puripia.com/wp-content/uploads/2019/05/해피스트닷컴-happist.com-HSTS-등록-현황-체크-결과.png)
![[쇼핑몰 구축기] 웹서버 NGINX에서 HTTP 보안 헤더(Security Headers) 적용 時 주의점 11 [쇼핑몰 구축기] 웹서버 NGINX에서 HTTP 보안 헤더(Security Headers) 적용 時 주의점 9](https://puripia.com/wp-content/uploads/2019/05/HTTP-보안-헤더HTTP-Security-Header-적용-여부-점검-결과-by-Mozilla-Observatory.jpg)
![[쇼핑몰 구축기] 웹서버 NGINX에서 HTTP 보안 헤더(Security Headers) 적용 時 주의점 12 HTTP 보안 헤더(HTTP Security Header) 적용 여부 점검 결과 by Security Headers Sponsored by netsparker](https://puripia.com/wp-content/uploads/2019/05/HTTP-보안-헤더HTTP-Security-Header-적용-여부-점검-결과-by-Security-Headers-Sponsored-by-netsparker-1024x949.png)
![[쇼핑몰 구축기] SSL/TLS 보안 등급 A+에 도전하는 Let’s Encrypt 인증서 세팅 방법 13 let's encrypt ssl test score 보안 인증 점수](https://puripia.com/wp-content/uploads/2019/05/lets-encrypt-ssl-test-score-보안-인증-점수.png)
![[쇼핑몰 구축기] SSL/TLS 보안 등급 A+에 도전하는 Let’s Encrypt 인증서 세팅 방법 14 nginx 서버에서 Cipher 리스트 찾는 명령 수행 후](https://puripia.com/wp-content/uploads/2019/05/nginx-서버에서-Cipher-리스트-찾는-명령-수행-후-1024x633.png)
![[쇼핑몰 구축기] SSL/TLS 보안 등급 A+에 도전하는 Let’s Encrypt 인증서 세팅 방법 15 모질라 재단에서 제안하는 옵션 적용 결과 세부 항목02](https://puripia.com/wp-content/uploads/2019/05/모질라-재단에서-제안하는-옵션-적용-결과-세부-항목02-771x1024.png)
![[쇼핑몰 구축기] 우커머스 청구 및 배송 필드 최적화 방법 16 우커머스 결제(checkout) 단계 중 청구 상세 내용 화면](https://puripia.com/wp-content/uploads/2019/05/우커머스-결제checkout-단계-중-청구-상세-내용-화면-586x1024.png)
![[쇼핑몰 구축기] 우커머스 청구 및 배송 필드 최적화 방법 17 우커머스 결제(checkout) 단계 중 청구 및 배송 필드 플레이스 홀드 내용](https://puripia.com/wp-content/uploads/2019/05/우커머스-결제checkout-단계-중-청구-및-배송-필드-플레이스-홀드-내용-580x1024.png)
![[쇼핑몰 구축기] 우커머스 배송비 표시 – 무료時 기본 배송비 숨기기 18 장바구니 모습, 무료와 기본 배송비가 모두 표현되고 있는 상황](https://puripia.com/wp-content/uploads/2019/05/장바구니-모습-무료와-기본-배송비가-모두-표현되고-있는-상황-1024x684.png)
![[쇼핑몰 구축기] 우커머스 배송비 표시 – 무료時 기본 배송비 숨기기 19 이미지에 대체텍스트 속성이 없습니다; 파일명은 장바구니-모습-무료만-표현된-상황-1024x649.png 입니다.](https://puripia.com/wp-content/uploads/2019/05/장바구니-모습-무료만-표현된-상황-1024x649.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 20 우커머스 배송 기본 설정 화면](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-기본-설정-화면-1024x516.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 21 우커머스 배송설정 화면](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송설정-화면-1024x647.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 22 우커머스 배송설정_배송구역 설정 화면](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송설정_배송구역-설정-화면-1024x764.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 23 우커머스 배송 구역 추가_도서산간지역 설정](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-추가_도서산간지역-설정-1024x574.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 24 [쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 10](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-추가_제주도지역-1024x568.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 25 우커머스 배송 설정_배송 방법 추가](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-설정_배송-방법-추가.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 26 우커머스 배송 구역 추가_도서산간지역 배송비용](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-추가_도서산간지역-배송비용-1024x395.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 27 [쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 11](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-추가_제주도-무료-배송-설정-1024x406.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 28 우커머스 배송 구역 추가_제주도 무료 배송 설정02](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-추가_제주도-무료-배송-설정02-1024x409.png)
![[쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 29 [쇼핑몰 구축기] 우커머스 배송 지역 및 배송비 설정 방법 12](https://puripia.com/wp-content/uploads/2019/05/우커머스-배송-구역-내-세부-세팅-제주도의-경우-1024x742.png)
![[쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 30 [쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 13](https://puripia.com/wp-content/uploads/2019/05/우커머스-원페이지-체크아웃-플로우-WooCommerce-One-Page-Checkout-flow.jpg)
![[쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 31 [쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 14](https://puripia.com/wp-content/uploads/2019/05/Woocommerce-one-page-checkout-and-layouts-screenshot-1-1024x864.jpg)
![[쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 32 [쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 15](https://puripia.com/wp-content/uploads/2019/05/퓨리피아-결제단계-모바일에서-보는-이미지-1.jpg)
![[쇼핑몰 구축기] 원페이지 체크아웃(One Page Checkout) 구현으로 구매 단계 줄이기 33 WooCommerce Direct Checkout Pro 원페이지 체크아웃 최적화 후 모습](https://puripia.com/wp-content/uploads/2019/06/WooCommerce-Direct-Checkout-Pro-원페이지-체크아웃-최적화-후-모습.jpg)
![[쇼핑몰 구축기] 바로구매 버튼 추가로 구매 단계 줄이기 34 [쇼핑몰 구축기] 바로구매 버튼 추가로 구매 단계 줄이기 16](https://puripia.com/wp-content/uploads/2019/05/엣지에서-장바구니와-바로구매를-나란히-배치하는-방법-1024x438.png)
![[쇼핑몰 구축기] 바로구매 버튼 추가로 구매 단계 줄이기 35 [쇼핑몰 구축기] 바로구매 버튼 추가로 구매 단계 줄이기 17](https://puripia.com/wp-content/uploads/2019/05/WooCommerce-Direct-Checkout-Pro-Screenshot_20190508-182123_Chrome.jpg)