본문으로 건너뛰기
개발 머꼬
개발 노트Nginx
hohyeon.dev34

정적 파일은 압축되는데 API 응답만 압축되지 않은 이유

  • #Engineering Note
  • #Nginx
  • #Performance

문제 발생

gzip on;을 넣었는데 JSON API 응답의 Content-Encoding이 비어 있었습니다. HTML은 압축되고 있었습니다.

$ curl -H "Accept-Encoding: gzip" -I https://dev.meokko.com/api/posts
# Content-Encoding 없음

원인 분석

세 가지 기본값이 겹쳐 있습니다. nginx 문서의 기본값을 보면 이유가 한 번에 드러납니다.

  • gzip 기본값은 off — 켜지 않으면 아무것도 압축하지 않습니다.
  • gzip_types 기본값은 text/html — 켜도 HTML만 대상입니다. JSON, CSS, JS는 명시해야 합니다.
  • gzip_proxied 기본값은 off프록시된 요청에 대한 압축이 기본적으로 비활성입니다.

우리 구성에서 HTML은 nginx가 직접 서빙하고 API는 upstream(Next.js)으로 프록시되므로, 딱 프록시된 응답만 빠진 것입니다.

해결 방안

  1. 세 가지를 함께 설정합니다.
gzip on;
gzip_types application/json application/javascript text/css text/plain image/svg+xml;
gzip_proxied any;
gzip_min_length 1024;
  1. 작은 응답은 압축하지 않습니다. gzip_min_length 기본값은 20바이트인데, 수백 바이트 응답은 압축 이득보다 CPU와 헤더 오버헤드가 큽니다 — 1KB 안팎이 흔한 기준입니다.

  2. 이미 압축된 형식을 빼둡니다. JPEG·PNG·WebP·zip은 다시 압축해도 줄지 않습니다. gzip_types에 넣지 않습니다.

  3. Vary: Accept-Encoding을 확인합니다. 압축 여부가 응답을 바꾸므로 캐시가 이를 알아야 합니다 — nginx가 붙여주는지, CDN이 유지하는지 확인합니다.

  4. upstream이 이미 압축했는지 봅니다. 애플리케이션이 자체 압축을 하고 있으면 nginx는 그대로 통과시킵니다 — 두 곳에서 켜면 CPU만 이중으로 씁니다. 한 곳에서만 합니다.

  5. 실제 응답으로 검증합니다. curl -H "Accept-Encoding: gzip" -IContent-Encoding: gzip이 오는지 확인하고, 전송 크기를 비교합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.