nginx를 이용한 웹에서의 zstd 압축 활성화

Sming·2024년 10월 9일
6
post-thumbnail

지난 글에 zstd의 존재, 그리고 장점에 대해서 알아보았고 이번에는 실제로 nginx를 이용하여 지원하는 환경에 따라 zstd compression을 지원하도록 해볼것입니다.

zstd-nginx-module

먼저 nginx에서 zstd 압축을 지원하는지부터 확인이 필요한데요. 다행히도 zstd-nginx-module이라는 모듈이 존재하여 다음을 이용하여 zstd 압축을 이용할 수 있어보입니다.

이제 이것을 우리의 nginx & docker 환경에서 한번 이용을 해보도록 하겠습니다. 먼저 zstd-nginx-module을 install을 해야합니다.

https://nginx-extras.getpagespeed.com/modules/zstd/#__tabbed_1_2 다음 문서에서 module을 install 하는 방법이 있는데요.

문제는 yum, dnf 형식으로만 install할 수 있기에 기존에 사용하던 nginx base image를 사용할 수 없습니다. (nginx base image는 alpine linux 기반이기에 apt 방식)

# 기존 Dockerfile

FROM nginx:1.25.0-alpine-slim

ARG PROFILE
ENV PROFILE=${PROFILE}

RUN mkdir /etc/nginx/env

COPY ./conf.d /etc/nginx/conf.d
COPY ./location /etc/nginx/location
COPY ./variable /etc/nginx/variable
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./env/.env.${PROFILE} /etc/nginx/env/.env.${PROFILE}

그렇기에 우리는 기존 nginx base image 대신 fedora image에서 dnf 를 이용하여 nginx와 zstd-nginx-module을 이용해야합니다.

# zstd-nginx-module 이용

FROM fedora:latest

ARG PROFILE
ENV PROFILE=${PROFILE}

RUN dnf -y install https://extras.getpagespeed.com/release-latest.rpm \
    && dnf -y install nginx nginx-module-zstd \
    && dnf -y install gettext

RUN mkdir /etc/nginx/env

COPY ./conf.d /etc/nginx/conf.d
COPY ./location /etc/nginx/location
COPY ./variable /etc/nginx/variable
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./env/.env.${PROFILE} /etc/nginx/env/.env.${PROFILE}

docker base image를 fedora를 이용하고 nginx-module-zstd, nginx를 설치하고 envsubst이용을 위한 gettext를 추가해줍니다.


이제 설치가 되었으니 실제 nginx.conf에 적용이 필요한데요. 적용자체는 매우 간단합니다. load_module을 이용하여
ngx_http_zstd_filter_module.so, ngx_http_zstd_static_module.so 2개의 모듈을 추가하면 됩니다.

user  nginx;
worker_processes  auto;

error_log  /dev/stdout;
pid        /var/run/nginx.pid;

load_module modules/ngx_http_zstd_filter_module.so; # 이 부분 추가
load_module modules/ngx_http_zstd_static_module.so; # 이 부분 추가

events {
    worker_connections  1024;
}

그 후에는 nginx에 gzip을 추가하듯이 압축을 위한 zstd 설정도 추가하면 됩니다.

    zstd on;
    zstd_types text/plain text/css application/json application/javascript text/html text/xml application/xml;
    zstd_comp_level 6;
    zstd_min_length 256;
  • zstd on: zstd 압축을 활성화합니다.
  • zstd_types: zstd 압축을 적용할 mime types들을 추가합니다.
  • zstd_comp_level: zstd의 압축 레벨입니다. 1 ~ 22사이의 수치로 정할 수 있고 숫자가 높아질수록 압축률이올라가지만 그에 비례하여 압축시간, cpu 사용률도 늘어나게 됩니다. (수치가 올라갈수록 올라가는 압축률보다 압축시간이 비약적으로 올라가기에 6으로 설정하였습니다.)
  • zstd_min_length: zstd 압축을 적용할 최소 용량입니다. 256byte이상이면 zstd압축이 되도록 설정하였습니다.

브라우저 호환성을 고려한 압축 설정

이제 zstd 압축이 가능한 상황까지는 만들었습니다. 하지만 이전 글에도 언급했듯이 아직 zstd 같은 경우 최신 브라우저에서만 이용가능하고 모든 브라우저에서 지원하는 상황은 아닙니다.

그렇기에 우리는 zstd를 지원하는 경우에는 zstd를, 지원하지 않는 경우에는 gzip을 이용하도록 설정할 것 입니다.

그러기 위해 Accept-Encoding 값을 본후 zstd가 있는 경우에는 zstd가 우선적으로 적용하고 그렇지 않는 경우에는 gzip을 적용하도록 하였습니다.

그리고 Content-Encoding Response header에 gzip, zstd 둘 중 하나를 넣어 브라우저에게 어떤 압축 알고리즘을 적용할것인지 알리면 됩니다.

location / {
    proxy_pass http://$web_ip:3000;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme; 

    set $encoding_type "";

    if ($http_accept_encoding ~* "gzip") {
        set $encoding_type "gzip";
    }

    if ($http_accept_encoding ~* "zstd") {
        set $encoding_type "zstd";
    }

    proxy_set_header Content-Encoding $encoding_type;
}

Next.js compress 고려하기

이렇게 적용후에 실제로 테스트를 해보니 zstd가 적용되지 않고 계속 gzip만 나오는 이슈가 있었습니다. 원인을 파악한 결과 바로 Next.js의 compress 설정과 연관이 있었습니다.

https://nextjs.org/docs/app/api-reference/next-config-js/compress 이 문서에도 나타나있듯 compress를 사용하면 nextjs가 내장해서 gzip 압축을 적용합니다. 그렇기에 nginx를 사용해서 gzip, zstd 압축을 이용하려면 next.config.js의 compress옵션을 false로 처리해야합니다.

실제 적용 결과

다음과 같이 최신 크롬에서는 정적인 파일에 대해서 Content-Encoding: zstd가 적용되어 압축된 상태를 볼 수 있습니다.

그렇다면 zstd를 지원하지 않는 safari 브라우저에선 어떨까요? 우리가 원하는대로 zstd대신에 gzip으로 압축된 상태를 볼 수 있습니다.

그래서 실제로 많은 용량이 감소했을까요?

사실 파일용량은 크게 줄지는 않았습니다. 이전글에서 용량별 gzip vs zstd를 비교한것을 보면 50kb대에서는 크게 gzip, zstd 압축 차이가 많이 나지는 않습니다. 또한 Next.js가 자체적 코드스플리팅으로 한 파일용량이 그렇게 커지지 않기때문이기도 하죠.

그렇다면 gzip을 쓰나 zstd를 쓰나 큰 차이가 없는걸까요?

그것은 아닙니다. 왜냐하면 저희는 압축속도, 압축해제속도에 대해서 gzip에 비해 2배 빠른 속도를 얻기도 하고 zstd의 진가는 용량이 커졌을때 나타나기때문에 만약 용량이 큰 라이브러리들을 많이 사용하게 될 경우 큰 효과를 얻을 수 있다고 생각됩니다.

현재 tiptap을 통하여 커스텀 웹 에디터를 서비스에 붙히고 있는데 용량이 꽤나 크기때문에 적용을 마친뒤 zstd를 통해 어느정도의 용량 이점을 얻었는지 추가로 공유해볼 예정입니다.

결론

zstd 써보세요^^ 호환성이 유일한 단점이지만 설명했듯이 Accept-Encoding을 통하여 브라우저 지원에 따라 gzip, zstd를 모두 지원해준다면 안 쓸 이유는 없어보입니다. 👍

profile
딩구르르

1개의 댓글

comment-user-thumbnail
4일 전

Would you be interested in Indian escorts when you were there? We serve agencies and people who are looking for Escorts in Udyog Vihar as well as the biggest platform for escorts in Gurgaon.

답글 달기