들어가며
오늘은 웹 서버 성능 최적화의 끝판왕, Nginx의 Gzip Static 기능을 공유해보려고 합니다.
웹 서비스를 운영하다 보면 JS, CSS 같은 정적 파일 용량 때문에 고민이 많으시죠?
보통 gzip on; 설정 하나로 해결하시곤 하는데, 과연 그게 최선일까요?
직접 수치로 증명한 결과를 보여드립니다!
실시간 Gzip 압축, 무엇이 문제일까?
우리가 흔히 쓰는 gzip on;은 '실시간 압축' 방식입니다. 클라이언트가 요청을 보낼 때마다 서버가 파일을 막 압축해서 보내주는 거죠.
•
문제점: 요청이 몰리면? 서버 CPU가 압축 계산하느라 비명을 지릅니다. 
•
성능 타협: 서버가 너무 힘들까 봐 압축 레벨을 낮게 설정하게 되고, 결국 전송 효율도 떨어지죠.
해결사 등장 Gzip Static 모듈
gzip_static은 "서버야, 고생하지 마. 내가 미리 압축해둔 파일(.gz) 보낼게!" 하는 방식입니다.
•
원리: 배포할 때 미리 최상위 레벨(Level 9)로 압축 파일을 만들어둡니다.
•
장점: Nginx는 계산할 필요 없이 파일만 던져주면 끝! CPU 사용량이 드라마틱하게 줄어듭니다.
직접 해보는 성능 테스트 (The Benchmark)
실제 운영 환경과 유사한 대용량 텍스트 파일(gzip_test.html)을 작성하여 wrk 도구를 이용해
실시간 압축(Gzip on) 환경과 사전 압축(Gzip Static) 환경을 각각 구성하여 동일한 조건에서 부하를 걸어보았습니다.
테스트 환경 및 명령어
•
대상 파일: gzip_test.html (대용량 텍스트 파일)
•
부하 조건: 2개 스레드, 100개 동시 연결, 10초간 테스트
•
명령어: ./wrk -t2 -c100 -d10s -H "Accept-Encoding: gzip" --latency http://localhost/gzip_test.html
실제 터미널 로그 분석
[Case 1] Gzip On (Level 5) 실행 결과
실시간으로 압축을 수행하다 보니 응답 속도(Latency)가 밀리고, 처리량도 초당 400건대에 머뭅니다.
•
호출 테스트 케이스 : gzip_test.html 파일 내 include 리소스
◦
gzip_test.txt
◦
jquery.js
Running 10s test @ http://localhost/gzip_test.html
Latency 212.82ms 56.33ms 408.60ms 84.23%
Req/Sec 233.34 42.08 350.00 67.00%
4649 requests in 10.01s, 110.04MB read
Requests/sec: 464.61
Transfer/sec: 11.00MB
JavaScript
복사
[Case 2] Gzip Static On 실행 결과
미리 압축된 파일을 전송만 하므로 지연 시간이 ms(밀리초)에서 us(마이크로초) 단위로 뚝 떨어집니다.
처리량은 30만 건으로 폭증합니다.
•
호출 테스트 케이스 : gzip_test.html 파일 내 include 리소스
◦
gzip_test.txt.gz
◦
jquery.js.gz
Running 10s test @ http://localhost/gzip_test.html
Latency 183.78us 78.15us 2.96ms 82.93%
Req/Sec 153.73k 3.91k 159.86k 79.50%
3059789 requests in 10.00s, 70.66GB read
Requests/sec: 305963.72
Transfer/sec: 7.07GB
JavaScript
복사
성능 비교 결과
항목 | 실시간 압축 (Dynamic) | 사전 압축 (Static) | 개선 수치 |
Nginx 설정 | gzip on; / gzip_comp_level 5; | gzip_static on; (Level 9 사전압축) | |
초당 요청 수 (RPS) | 464.61 req/s | 305,963.72 req/s | 약 658배 증가 |
평균 지연 시간 | 212.82 ms | 183.78 us (0.18ms) | 약 1,150배 지연 감소 |
최대 지연 시간 | 408.60 ms | 2.96 ms | 약 138배 단축 |
초당 전송량 | 11.00 MB/s | 7.07 GB/s | 약 657배 증가 |
결과 요약 | CPU가 압축하느라 병목 발생 | CPU 부하 없이 I/O 속도 풀가동 |
결과 분석
•
실시간 압축 (Gzip On): 평균 응답 속도가 212ms까지 늘어났고, 초당 464번의 요청만 처리 가능했습니다. 서버 CPU가 압축 연산을 수행하느라 병목이 발생했기 때문입니다.
•
사전 압축 (Gzip Static): 응답 속도가 무려 183us(마이크로초) 단위로 줄어들었습니다! 초당 처리량은 무려 30만 건을 넘어섰으며, 초당 전송량은 7GB/s에 달합니다.
이 결과는 서버가 압축에 쓰던 CPU 자원을 온전히 데이터 전송에만 집중했을 때 얼마나 강력한 퍼포먼스를 내는지 여실히 보여줍니다.
나도 적용해보기 (Nginx 설정)
해당 기능을 적용하기 위 Nginx 설정 파일의 각 옵션들을 소개합니다!
(단, Nginx 설치 시 http_gzip_static_module이 포함되어 있어야 합니다.)
http {
# //사전 압축 파일(.gz)이 있으면 우선 전송
gzip_static on;
# //압축 파일이 없으면 실시간으로라도 압축 (안전장치)
gzip on;
# //압축에서 제외할 최소 파일 크기 (너무 작은 파일은 압축 효율이 떨어짐)
gzip_min_length 1024;
# //압축 레벨 (1~9, 숫자가 높을수록 압축률은 좋지만 CPU 점유율 상승)
# //보통 5 또는 6이 성능과 리소스 사이의 황금 밸런스이지만, 서버의 CPU 부하를 고려
gzip_comp_level 5;
# //압축에 사용할 버퍼 설정
# //기본적으로 시스템 페이지 크기에 따라 자동 설정되나,
# //대용량 응답이 많은 경우 명시적으로 지정하여 디스크 I/O를 줄일 수 있습니다.
gzip_buffers 16 8k;
# //압축을 적용할 파일 형식 (이미지는 효과가 없으므로 텍스트 기반 위주)
gzip_types
text/plain
text/css
application/json
application/javascript
application/xml
text/javascript;
# //프록시 서버(CDN 등)를 거칠 때도 압축 적용 여부 결정
gzip_proxied any;
# //브라우저가 gzip을 지원하는지에 따라 Vary 헤더 추가
# //vary 헤더를 추가하면 Accept-Encoding 헤더가 추가되어 브라우저 캐싱 효율성을 높인다.
gzip_vary on;
# //오래된 브라우저(IE6 등)는 압축에서 제외
gzip_disable "msie6|Mozilla/4";
}
JavaScript
복사
꿀팁! 배포 전에 미리 호출 대상 정적 리소스를 .gz 압축하여 만들어두는 걸 잊지 마세요!
마치며
테스트 결과가 말해주듯, 정적 리소스가 많은 서비스에서 gzip_static은 최소의 비용으로 최대의 효과를 내는 최적화 기법입니다.
1.
CPU 자원 절약: 서버가 더 중요한 비즈니스 로직(WAS 연산 등)에 집중할 수 있어요.
2.
안정성 향상: 갑작스러운 트래픽 폭주에도 서버가 끄떡없습니다.
3.
지연 시간 단축: 유저는 0.1ms 만에 압축된 데이터를 받아볼 수 있습니다.
여러분의 서버는 지금 실시간으로 고생하고 있진 않나요? 지금 바로 gzip_static을 검토해보세요! 
명주호 프로
오픈소스사업부 오픈소스기술팀
에스코어에서 미들웨어 엔지니어로 근무하며, 삼성 그룹사를 비롯한 국내 주요 대기업과 공공기관의 미들웨어 설계 및 기술지원을 담당하고 있어요 


