압축 기술 · 8 min read · Sep 15, 2025

mod_gzip - 압축된 콘텐츠 제공하기 - 페이지 9

저자: Michael Schröpl

협상을 통한 압축

configurable 압축 기능인 mod_gzip을 사용하는 것은 궁극적으로 항상 일종의 콘텐츠 협상이어야 하며, 즉 요청된 URL에 대해 특정 HTTP 헤더 내의 정보에 따라 조건부로 서로 다른 콘텐츠를 제공하는 것입니다.

반면에 HTTP는 임시 저장을 허용합니다. HTTP 요청에 대한 응답을 캐시에 저장하는 것은 특히 프록시 서버를 사용할 때 그렇습니다. 만약

  1. HTTP 클라이언트가 요청을 보냅니다,
  2. 해당 응답이 압축된 형태로 제공되고 일부 프록시에 저장됩니다.
  3. 이후 다른 HTTP 클라이언트가 해당 URL에 대한 요청을 제출합니다,

그렇다면 프록시 서버는 - 추가 정보가 없는 상태에서 - 문제를 겪게 됩니다:

  • 이 두 번째 HTTP 클라이언트에게 캐시된 콘텐츠를 제공할 권리가 있는가, 아니면
  • 요청을 HTTP 서버로 전달해야 하는가?

오직 HTTP 서버만이 궁극적으로 (해당 필터 규칙을 포함하는 구성에 따라) 두 번째 HTTP 클라이언트가 압축된 응답 데이터를 받을 수 있는지를 확인할 수 있습니다.

그런데 이것은 압축 절차를 단독으로 사용하는 효과가 아니라 프록시 서버의 캐시 또는 유사한 메모리 내에서 URL로 명확하게 지정할 수 없는 HTTP 데이터 캐싱에 대한 일반적인 문제입니다. 여기에는 모든 유형의 협상 절차와 인증 데이터 또는 쿠키와 같은 HTTP 헤더에 추가 정보를 제출하는 것이 포함됩니다.

성능 요구 사항

물론, 클라이언트와 서버 간의 경로에 존재하는 모든 프록시 서버에 대해 해당 응답 데이터의 캐싱을 명시적으로 거부하여 문제를 피할 수 있습니다 (HTTP/1.0의 Expires:Pragma: 헤더와 HTTP/1.1의 Cache-Control: 사용).

그러나 압축의 목표는 데이터 전송 속도를 높이는 것입니다 (데이터 양을 줄임으로써) - 그리고 데이터 캐싱은 같은 목표를 달성합니다 (HTTP 서버에 대한 접근을 줄임으로써). 그리고 하나의 성능 최적화가 다른 성능 최적화를 사용할 수 없게 해서는 안 되며, 특히 이 두 가지는 서로를 대체하는 것이 아니라 특정 경우에 효과적으로 상호 보완할 수 있습니다.

협상 매개변수에 대한 정보

HTTP 사양에는 HTTP 서버가 프록시 서버에 대해 알릴 수 있는 Vary HTTP 헤더의 정의가 포함되어 있습니다.

  • 응답이 URL 요청의 고유한 결과인지 여부 또는
  • 동일한 URL에 대한 요청의 다른 속성이 다른 결과를 초래할 수 있는지 여부.

그 값은 이 특정 요청에 대한 응답을 제공하는 데 관련된 다른 HTTP 헤더의 이름 목록을 포함할 수 있습니다. 따라서 HTTP 서버는 어떤 HTTP 헤더가 제공된 콘텐츠에 대한 결정에 영향을 미쳤는지를 프록시 서버에 알릴 수 있습니다.

프록시 서버가 HTTP 서버에 요청을 전달하고 나중에 응답을 캐시에 저장하려고 할 때, HTTP 서버의 응답이 도착할 때 원래 요청의 HTTP 헤더를 여전히 보유하고 있어야 합니다.

이제 HTTP 서버가 응답의 조건부 콘텐츠를 해당 Vary 헤더로 표시하면

  • 프록시 서버는 이 응답의 콘텐츠뿐만 아니라 요청의 모든 관련 HTTP 헤더 정보를 (응답의 Vary HTTP 헤더 값 목록에 열거된 이름의) 캐시에 저장해야 하며,
  • 후속 요청의 해당 HTTP 헤더 정보가 원래 요청의 값과 적어도 ‘일치’하지 않는 한 이 캐시된 콘텐츠를 추가 요청에 대한 응답으로 제공해서는 안 됩니다. 즉, 이러한 헤더 각각에 대해 원래 요청의 값과 의미적으로 동일해야 합니다.

HTTP 서버에 대한 결과 제한

이전 설명은 프록시 서버가 HTTP 응답의 조건부 제공을 올바르게 처리할 수 있는 방법을 보여주었습니다 (콘텐츠 협상의 결과로) - 최대한 캐싱 효과를 활용한다고 가정할 때

  • HTTP 서버가 협상 매개변수에 대한 충분한 정보를 프록시 서버에 제공하고
  • 프록시 서버가 다른 HTTP 클라이언트의 동일한 URL에 대한 후속 요청의 경우 해당 정보를 보유하고 있어야 합니다.

그러나 후자는 협상 프로세스의 자유도를 제한하는 것을 의미합니다. 왜냐하면 프록시 서버가 HTTP 요청 내의 정보에만 독점적으로 기반하여 캐시 콘텐츠를 제공할 수 있는지 여부를 결정해야 한다면, HTTP 서버의 협상 규칙은 HTTP 헤더 내용 외의 어떤 것에도 참조해서는 안 되기 때문입니다!

하지만 불행히도 이 전제 조건은 mod_gzip에 의해 충족되지 않습니다. 제공된 여섯 가지 필터 규칙 클래스 중에서

  • 두 개의 ‘합법적인’ 규칙 (reqheaderuri)는 오직 HTTP 헤더 내용만을 참조하지만
  • 네 개의 ‘불법적인’ 규칙 (rspheader, handler, filemime)은 HTTP 서버에 의한 요청 평가 중에만 사용할 수 있는 정보를 참조합니다.

따라서 mod_gzip이 향상된 서버가 이러한 ‘불법적인’ 필터 규칙 중 하나를 사용하면 프록시 서버는 더 이상 캐시 콘텐츠의 적용 가능성에 대해 올바르게 결정할 수 없습니다.

이렇게 되면 mod_gzip이 프록시 서버에 과부하가 명백하다고 알리더라도 (이 요청에 대해 중요한 필터 규칙 클래스의 전체 목록을 Vary: 헤더 내에 제공하는 것이 법적이라면) 프록시 서버가 할 수 있는 것은 이러한 네 개의 ‘불법적인’ 필터 규칙 클래스 중 하나의 발생을 기준으로 응답 콘텐츠를 캐시하지 않는 것입니다.

이것만으로도 나쁘지 않을 것입니다 - HTTP 서버가 ‘합법적인’ 규칙만 사용한다면 최적으로 프록시 서버와 협력할 수 있을 것입니다.

하지만 불행히도 mod_gzip 1.3.19.1a에서는 그렇게 하는 것이 불가능합니다.

mod_gzip 1.3.19.1a를 Apache 1.3 아키텍처에 통합하는 것은 상대적으로 복잡한 방식으로 이루어집니다:

  • 처리 단계 1에서 mod_gzip은 이 요청의 결과를 처리하는 데 관심이 있는지 여부를 확인하고 준비합니다 - 네 가지 클래스의 규칙에 따라 (reqheader, uri, filehandler, 즉 두 개의 ‘합법적인’ 및 두 개의 ‘불법적인’ 규칙 클래스)
  • 처리 단계 2에서 mod_gzip은 이제 (이제 사용 가능한) 응답 콘텐츠를 실제로 압축해야 하는지 여부를 확인합니다 - 두 개의 클래스의 규칙에 따라 (rspheadermime, 두 개의 ‘불법적인’ 규칙 클래스).

압축 요청의 성공적인 허가는 적어도 어느 한 단계에서 하나의 포함 규칙의 충족이 필요하며 (모든 제외 규칙의 비충족).

그러나 단계 2의 포함 규칙 클래스는 ‘불법적’이므로 현재 mod_gzip 구현에서 성공적인 압축을 위한 관련 필터 규칙 클래스 목록은 반드시 하나의 ‘불법적인’ 규칙 클래스를 포함해야 합니다.

따라서 프록시 서버에 캐시 콘텐츠의 적용 가능성에 대해 결정할 수 있는 정보를 제공하는 것은 불가능합니다 - 제출된 정보는 항상 프록시 서버의 이해를 초과할 것입니다.

mod_gzip 1.3.19.2a 및 이후의 Vary 헤더

버전 1.3.19.2a부터 mod_gzip은 Vary: 헤더를 전송합니다 - 모듈이 최소한 한 번 관련된 모든 요청에 대해 (압축된 데이터가 제공되었는지 여부에 관계없이).

현재 mod_gzip의 연구 상태에서 요청 (응답이 실제로 압축된 형태로 제공되었는지 여부에 관계없이)은 잠재적으로 협상입니다:

  • 적어도 Accept-Encoding HTTP 헤더에 대해, 그리고
  • 아마도 다른 HTTP 헤더에 대해서도 (즉, reqheader 클래스의 필터 규칙 내에서 발생하는 모든 것)

현재 mod_gzip은 최적의, 즉 필요한 최소한의 Vary: 헤더 집합을 생성할 수 없습니다 - 이를 위해서는 mod_gzip의 규칙 평가 절차를 완전히 재작성해야 합니다.

첫 번째 단계로, 모듈은 버전 1.3.19.2a부터 Vary: 헤더를 전송하여

  • Accept-Encoding과 함께
  • reqheader 규칙 내에서 사용되는 모든 헤더의 이름을 포함합니다.

이러한 각 규칙은 협상의 결과에 차이를 만들 수 있으며, 이러한 경우 결과는 수신된 HTTP 헤더의 값에 따라 달라집니다. 특정 경우에는 이것이 너무 많을 수 있으며 (그렇게 되면 콘텐츠의 효율적인 캐싱을 방해할 수 있음), 적어도 시작할 수 있는 것입니다.

이 전략의 개선으로, mod_gzip 1.3.26.1a는 요청의 압축이 mod_gzip_item_exclude 규칙으로 거부된 경우 Vary: 헤더를 전송하지 않습니다.

  • file,
  • uri rsp.
  • handler

유형 - 이 규칙의 평가는 수신된 HTTP 헤더에 따라 달라질 수 없으므로 이러한 경우 실제로 협상이 전혀 이루어지지 않았습니다.

압축되지 않은 형태로 제공될 수 없는 파일에 대해 Vary: 헤더가 전송되지 않도록 하려면, mod_gzip을 끄면 됩니다.

GIF 이미지에 대해 Vary: 헤더가 전송되지 않는 예시는 다음과 같습니다:

  
 mod_gzip_on No  

앞으로의 버전에서 다음 작업이 남아 있습니다:

  • 현재 요청에 대한 반응이 절대 압축된 데이터를 제공할 수 없다는 것을 모든 가능한 경우에 인식합니다. 이는 요청의 속성과 무관한 mod_gzip_item_exclude 규칙이 작동할 때입니다.
  • HTTP 헤더 이름 목록으로 설명할 수 없는 협상이 발생했음을 인식합니다 - 이 경우 Vary: * 헤더가 전송되어야 하며 (mod_gzip에 대한 문서는 이러한 지침이 절대적으로 필요할 때만 사용되도록 명시적으로 지적해야 합니다. 이는 캐싱 프록시의 작업에 부정적인 영향을 미칠 것입니다).
  • 모든 reqheader 규칙의 헤더 이름 중 일부만 Vary: 헤더에 필요할 수 있는 구성이 가능한지 다시 확인합니다 - 이름이 적을수록 프록시 캐시에 병렬로 저장해야 하는 변형이 적습니다.

HTTP 헤더 외의 다른 차원에 대한 협상

특정 구성 지침을 사용할 때 mod_gzip은 HTTP 헤더 이름으로 표현할 수 없는 차원에 대해 협상을 수행합니다. 이는 다음 지침에 적용됩니다:

  • mod_gzip_min_http (필요한 최소 HTTP 버전) 및
  • mod_gzip_handle_methods (처리할 HTTP 메서드)

두 경우 모두 mod_gzip은 프록시에게 HTTP 헤더 이름을 알려줌으로써 수행된 작업을 설명할 수 없습니다. HTTP/1.1 사양에 따른 적절한 반응은 Vary: * HTTP 헤더를 전송하는 것입니다.

mod_gzip 1.3.26.1a는 mod_gzip_min_http 지침이 사용된 경우 Vary: * 헤더를 전송합니다.

mod_gzip_handle_methods 지침에 대해서는 현재 동일한 URI에 대해 서로 다른 HTTP 메서드를 사용하는 두 HTTP 요청이 실제로 동일한 HTTP 엔터티를 요청하는지 여부가 아직 명확하지 않은 것 같습니다. 이는 이 지침을 사용할 때 Vary: * 헤더를 전송해야 하는지 여부를 결정하며, 향후 릴리스에서 해결해야 할 문제입니다.

하지만 이 경우 프록시 서버는 수행된 협상의 유형을 이해할 수 없으므로 이 마크가 있는 응답을 캐시할 수 있는 권한이 없습니다.

따라서 이러한 지침 중 하나를 사용하면 이 HTTP 서버에서 전송되는 모든 응답의 프록시 캐싱이 완전히 비활성화됩니다, 압축된 형태든 비압축된 형태든 관계없이. 따라서 이러한 지침 중 하나를 더 이상 사용하지 않는 것이 좋습니다.

사용자 에이전트의 특별한 경우

프록시 캐시에 서로 다른 협상 매개변수의 변형을 병렬로 저장하는 것은 실제로 발생할 수 있는 값이 몇 개 없을 경우 합리적일 수 있습니다 - 예를 들어 Content-Encoding의 경우. 가능한 값이 많으면 변형을 병렬로 저장하는 것은 더 이상 실행 가능하지 않습니다.

정확히 이것이 HTTP 클라이언트의 식별자로서 UserAgent 이름에 적용됩니다. 각 브라우저의 하위 버전은 브라우저의 이름과 버전뿐만 아니라 추가 정보(국가 언어, 운영 체제 이름 및 버전 등)를 포함하는 복잡한 UserAgent 문자열을 전송합니다. 알려진 UserAgent 문자열은 수백 개가 있으며, 이 UserAgent 문자열을 조작하는 여러 메커니즘이 있습니다. 일부 브라우저(예: Opera)는 사용자가 다른 브라우저로 가장할 수 있도록 UserAgent 문자열의 내용을 명시적으로 선택할 수 있도록 허용합니다(기술적으로 무능력한 웹 페이지 제작자들이 브라우저 이름을 기반으로 사이트를 구축하고 불필요하게 일부 브라우저를 제외하거나, 사용자가 사용하는 컴퓨터 장비에 대한 세부 정보를 불필요하게 표시하고 싶지 않기 때문입니다).

HTTP 클라이언트의 신원에 따라 압축된 웹 페이지를 조건부로 제공하는 것이 얼마나 합리적일 수 있는지는 여전히 의문입니다(예: Netscape 4의 수많은 버그와 관련하여). 그러나 HTTP 협상의 기반으로 UserAgent 문자열을 사용하는 단점은 한편으로는 이 HTTP 헤더의 내용이 너무 다양하여 신뢰할 수 있는 결론을 도출하기 어렵고, 다른 한편으로는 모든 캐싱 프록시가 이러한 협상 변형에 대해 동일한 URL에 대한 요청 결과를 병렬로 유지할 수 없을 만큼 너무 많은 서로 다른 값을 포함하고 있다는 것입니다.

버전 1.3.19.2a부터 mod_gzip은 구성에서 해당 지침이 사용된 경우 협상의 매개변수로 HTTP 헤더 User-Agent:를 설명하는 Vary: 헤더를 전송합니다. 그러나 후속 요청이 정확히 동일한 User-Agent: 값을 포함할 확률은 매우 낮습니다 (따라서 이 클라이언트는 이미 저장된 콘텐츠를 받을 수 있습니다).

실제로 HTTP 서버는 (구성에 따라 기능적으로 동등하다고 가정되는) UserAgents의 큰 집합을 협상 중에 동일하게 처리합니다 - 그러나 Vary: 헤더는 HTTP 서버가 협상 중에 HTTP 서버에 의해 중요하다고 평가된 UserAgent 문자열의 어떤 부분이 중요한 콘텐츠였는지를 캐싱 프록시에 알릴 수 없습니다. 프록시 서버는 UserAgent가 어떤 역할을 했다는 것만 알 수 있으며, 이를 인식한 프록시는 개별 UserAgents를 다르게 처리해야 합니다. HTTP 서버가 그렇게 행동하지 않더라도 말입니다.

따라서 UserAgent HTTP 헤더를 평가하는 필터 규칙을 사용하면 이 방식으로 생성된 응답 패킷에 대한 모든 캐싱이 완전히 비활성화됩니다. mod_gzip의 사용자는 이 효과를 절대적으로 인식해야 하며 - 따라서 가능하다면 이러한 HTTP 클라이언트 간의 동일한 유형의 차별화를 제공하기 위해 가능한 한 적은 수의 서로 다른 값을 가진 다른 필터 방법을 사용해야 합니다.

이 문서의 원본 위치:

http://www.schroepl.net/projekte/mod_gzip/cache.htm

Share: X/Twitter LinkedIn

새 게시물을 받은 편지함에서 받기

스팸은 없습니다. 언제든지 구독 해지 가능합니다.