정적은 Brotli, 동적은 zstd: 2026년 웹 압축을 나누는 기준

🤖 AI Summary
웹 응답 압축이 오랫동안 gzip 하나로 충분하던 시절은 지났습니다. 이제 압축률이 더 높은 Brotli(br)와, 빠른 속도에서 더 나은 압축률을 내는 Zstandard(zstd)가 더해져 셋이 공존합니다. 이때 무엇을 쓸지는 브라우저가 일방적으로 정하지 않고, Accept-Encoding과 Content-Encoding으로 클라이언트와 서버가 합의합니다. 실무에서 자리잡은 기준은 분담입니다. JS·CSS·폰트 같은 정적 자산은 한 번 압축해 여러 번 재사용하므로 느려도 압축률이 가장 높은 Brotli 최고 레벨로 미리 압축하고, 매 요청마다 즉석에서 압축해야 하는 동적 응답은 빠른 zstd로 처리하는 방식이죠. 이 글은 Content-Encoding 협상의 원리, gzip·Brotli·zstd의 좌표(압축률·속도·레벨·표준 문서), 그리고 도입 전 반드시 확인할 점을 1차 출처로 정리합니다.
블로그 목차
압축 코딩이 하나에서 셋으로 늘었습니다
오랫동안 웹 서버의 응답 압축은 사실상 gzip 하나였습니다. 거의 모든 브라우저가 이해하고, 켜기도 쉬웠으니까요. 그런데 같은 데이터를 더 작게 줄이는 Brotli, 그리고 빠른 속도에서도 gzip보다 잘 줄이는 Zstandard(zstd)가 차례로 표준에 들어오면서 선택지가 셋으로 늘었습니다.
선택지가 늘었다는 건 "무엇을 켜느냐"가 곧 응답 크기와 처리 비용을 가르는 결정이 되었다는 뜻입니다. 다만 이 글은 일반적인 사이트 속도 이야기가 아니라, HTTP 응답을 어떤 코딩으로 압축할지라는 한 겹에 집중합니다. 먼저 그 코딩이 어떻게 정해지는지부터 보겠습니다.

Content-Encoding은 고르는 게 아니라 합의하는 것
압축 코딩은 서버가 일방적으로 강제하지 않습니다. 클라이언트가 요청에 Accept-Encoding 헤더로 "나는 zstd, br, gzip을 이해한다"라고 지원 목록을 알리면, 서버가 그중 하나를 골라 응답하고 Content-Encoding 헤더로 "이건 zstd로 압축했다"라고 표시합니다. 이 협상 규칙은 RFC 9110이 정의하며, 클라이언트는 품질값(q-value)으로 선호 순위까지 표현할 수 있습니다.
핵심은 합의가 안 되면 자연스럽게 내려간다는 점입니다. 클라이언트가 zstd를 알리지 않으면 서버는 Brotli나 gzip으로, 그것도 아니면 무압축으로 응답합니다. 그래서 새 코딩을 켜는 일이 곧 구형 클라이언트를 버리는 일은 아닙니다. 지원하는 쪽에는 더 나은 코딩을, 아닌 쪽에는 기존 코딩을 주는 구조죠.
한 가지 구분할 점이 있습니다. 여기서 말하는 압축은 표현(payload)을 줄이는 Content-Encoding이고, 전송 구간을 다루는 Transfer-Encoding과는 다릅니다. 둘은 계층이 달라 섞어 생각하면 안 됩니다.

gzip·Brotli·zstd, 세 코딩의 좌표
세 코딩은 경쟁자라기보다 쓰임이 다른 도구에 가깝습니다. 표준 문서와 압축 레벨, 그리고 압축률과 속도의 위치가 서로 다릅니다.

표에서 보듯 Brotli는 압축률이 가장 높은 대신 압축이 느리고, zstd는 비슷한 압축률을 훨씬 빠르게 냅니다(위 수치는 Cloudflare가 자사 트래픽에서 측정한 값으로, 데이터 종류에 따라 달라집니다). 표준 문서를 적을 때는 zstd는 RFC 8878을 쓰면 됩니다. 먼저 나온 RFC 8478은 RFC 8878로 대체되었습니다.
정적은 Brotli, 동적은 zstd로 나누는 이유
압축률이 높은 Brotli도, 빠른 zstd도 모든 자산의 정답은 아닙니다. 갈림길은 "이 압축을 몇 번이나 재사용하는가"입니다.
정적 자산(JS·CSS·폰트 등 텍스트 자산): 빌드 시점에 한 번 압축해 두면 이후 수많은 요청에 같은 결과를 그대로 내려보냅니다. 압축이 몇 초 걸려도 그 비용은 한 번뿐이라,압축률이 가장 높은 Brotli 최고 레벨(11)로 미리 압축(precompress)해 두는 편이 이득입니다.동적 응답(API·매번 달라지는 HTML): 내용이 요청마다 달라 미리 압축해 둘 수 없고, 매 요청에 즉석에서 압축해야 합니다. 이때는 압축에 드는 시간이 곧 응답 지연이 되므로,같은 속도에서 gzip보다 잘 줄이는 zstd가 적합합니다.
정리하면 Brotli의 느린 압축은 "한 번 압축해 여러 번 재사용"으로 비용을 분산할 수 있을 때 빛나고, zstd의 빠른 압축은 "매번 새로 압축"해야 할 때 빛납니다. 두 코딩은 같은 서버에 함께 켜 두고 자산 성격에 따라 나눠 쓰는 것이지, 둘 중 하나를 고르는 문제가 아닙니다.

도입 전 확인할 것
분담 원리를 알았다면, 실제로 켜기 전에 다음을 점검하면 시행착오를 줄일 수 있습니다.
브라우저 지원과 HTTPS 전제: Brotli는 caniuse 기준(2026년 6월) 약 95%로 보편 지원이고, zstd는 약 80%로 Chrome·Edge 123, Firefox 126, Safari 26부터 지원합니다(26.3에서 완전 지원). 특히 Chrome은 HTTPS에서만 zstd를 협상하므로, 평문 HTTP 구간에서는 zstd가 적용되지 않습니다.서버·CDN의 모듈 지원: 기본 nginx 코어에는 zstd도 Brotli도 들어 있지 않습니다. 직접 운영이라면 third-party 동적 모듈(또는 Brotli의 경우 상용 NGINX Plus 모듈)을 빌드해 올려야 합니다. CDN을 쓴다면 CDN 설정에서 켜는 편이 간단합니다. 예를 들어 Cloudflare는 2024년 9월 25일부터 zstd 응답 압축을 제공하고, 미지원 클라이언트에는 Brotli·gzip·무압축으로 자동 fallback합니다.압축해도 의미 없는 자산 구분: 이미 압축된 형식인 JPEG·PNG·WebP 같은 이미지나 동영상, zip 같은 아카이브는 다시 압축해도 거의 줄지 않고 CPU만 씁니다. 텍스트 계열(HTML·CSS·JS·JSON·SVG·폰트)에 압축을 집중하는 것이 맞습니다.공유 사전(dictionary) 압축은 별개 주제: zstd·Brotli에는 공유 사전을 쓰는 별도 인코딩(dcz·dcb)이 있는데, 이는 일반 zstd·br와 다른 토큰입니다. 기본 분담을 먼저 정리한 뒤 따로 검토할 영역으로 두는 편이 혼선을 줄입니다.
이것만 기억하세요
웹 응답 압축은 이제 gzip 하나가 아니라 gzip·Brotli·zstd 셋이 공존합니다. 무엇을 쓸지는 Accept-Encoding과 Content-Encoding으로 클라이언트와 서버가 협상하고, 합의가 안 되면 gzip이나 무압축으로 내려가므로 구형 클라이언트가 깨지지 않습니다. 실무 기준은 분담입니다. 정적 자산은 한 번 압축해 재사용하므로 압축률이 가장 높은 Brotli 최고 레벨(11)로 미리 압축하고, 동적 응답은 매번 즉석 압축해야 하므로 빠른 zstd가 적합합니다. 표준 문서는 zstd가 RFC 8878(8478은 폐기), Brotli가 RFC 7932, 협상은 RFC 9110입니다. 지원은 Brotli 약 95퍼센트, zstd 약 80퍼센트(Chrome·Edge 123, Firefox 126, Safari 26부터)이며 Chrome은 HTTPS에서만 zstd를 협상합니다. nginx 코어에는 둘 다 없어 모듈이 필요하고, CDN을 쓰면 설정으로 켤 수 있습니다.
자주 묻는 질문 (FAQ)
Q. gzip을 쓰고 있는데 Brotli나 zstd로 바꿔야 하나요?
한쪽만 골라야 하는 문제가 아니에요. 세 코딩은 Content-Encoding 협상으로 공존합니다. 서버에 Brotli와 zstd를 함께 켜두면 클라이언트가 Accept-Encoding으로 알린 지원 목록에 맞춰 서버가 코딩을 고르고, 둘 다 지원하지 않는 오래된 클라이언트에는 gzip이나 무압축으로 자동 fallback해요. 그래서 gzip을 없애기보다 Brotli와 zstd를 추가로 켜는 방향이 일반적입니다.
Q. 정적은 Brotli, 동적은 zstd라고 나누는 이유가 뭔가요?
압축에 드는 시간을 몇 번이나 재사용하느냐가 다르기 때문이에요. JS·CSS·폰트 같은 정적 자산은 빌드 때 한 번만 압축해 수많은 요청에 재사용하니, 느려도 압축률이 가장 높은 Brotli 최고 레벨(11)이 유리합니다. 반면 API나 매번 달라지는 HTML 같은 동적 응답은 요청마다 즉석 압축해야 하니, 같은 속도에서 gzip보다 잘 줄이는 zstd가 적합해요.
Q. zstd의 Content-Encoding 표준 문서는 무엇인가요?
RFC 8878(2021년 2월)이에요. 이 문서가 zstd 포맷과 함께 HTTP에 'zstd' 토큰을 등록했습니다. 먼저 나온 RFC 8478은 RFC 8878로 대체(폐기)됐으니 인용할 때는 8878을 쓰면 됩니다. Brotli는 RFC 7932, gzip 포맷은 RFC 1952이고, Accept-Encoding과 Content-Encoding 협상 자체는 RFC 9110이 정의해요.
Q. 브라우저 지원은 충분한가요?
Brotli는 caniuse 기준(2026년 6월) 약 95%로 사실상 모든 모던 브라우저가 지원해요. zstd는 약 80%로 Chrome·Edge 123, Firefox 126, Safari 26부터 지원합니다(26.3에서 완전 지원). 다만 Chrome은 HTTPS에서만 Accept-Encoding에 zstd를 알리므로, 평문 HTTP에서는 zstd 대신 Brotli나 gzip으로 처리돼요. 미지원 클라이언트는 fallback으로 받기 때문에 호환성 문제는 크지 않습니다.
Q. nginx에 켜기만 하면 zstd가 되나요?
기본 nginx 코어에는 zstd도 Brotli도 들어 있지 않아요. zstd는 third-party 동적 모듈을, Brotli는 third-party 모듈이나 상용 NGINX Plus 모듈을 따로 설치해야 합니다. 그래서 직접 운영 환경에서는 모듈 빌드와 검증이 필요하고, CDN을 쓴다면 CDN 단에서 켜는 편이 간단해요. 예를 들어 Cloudflare는 2024년 9월 25일부터 zstd 응답 압축을 제공합니다.



