안녕하세요... 요전에 포스트한 HTTP 압축에 관한 글에서 IIS 6.0의 HTTP 압축 설정 방법을 소개하면서 파일 확장자 로 압축하는 IIS 6.0의 단점을 지적한 바 있습니다. 그래서 함 만들어 봤습니다. HTTP 압축을 수행하는 HTTP 모듈(module)로서 파일 확장자가 아닌 Content-Type에 의해 압축을 수행하며, 작은 파일 크기는 압축을 해봤자 오히려 손해이므로 일정 크기를 넘어가면 압축을 수행하도록 구성했습니다. 소스 코드는 아직 공개할 단계가 아닌 것 같고, DLL 만을 공개하고자 합니다. 필요하신 분들은 다운로드 받아 사용해 보시고 피드백 주십시요.

HTTP Compression Module

IIS 6.0은 HTTP 압축 기능을 공짜로(요거이 중요하다) 지원하며 그 능력 역시 나쁘지 않은 것으로 평가되고 있다. 하지만 IIS 6.0의 압축 기능은 설정이 용이하지 않고 파일 확장자에 의거하여 압축을 수행한다는 단점이 있다. 또한 IIS 6.0을 직접 설정할 수 없는 사용자(호스팅으로 세들어 사는 불쌍한 세입자들.... 제가 그렇답니당...)는 IIS 6.0의 압축 기능은 그림의 떡이다. 요런 단점을 보완하고자 HTTP 압축을 수행하는 ASP.NET 모듈을 만드러 보았다. 단꿀과 물엿, 버터와 쇼트닝유가 흐르는 압축의 세계에 빠져 볼 것인가 ? 아니면 귀차니즘 젖어 느리게 뜨는 사이트의 응답속도에 "우리 사이트가 아니네?" 하고 쌩깔 것인가?

Http Compress Module Download Now

주) HttpCompress 모듈의 저작권은 필자에게 있으며 어떠한 보증도 포함하고 있지 않습니다. 이 모듈을 개인 사이트가 아닌 상업적 사이트나 커뮤니티 사이트에 사용하고자 하는 경우, 필자의 허락을 얻어야 합니다. 또한 이 소프트웨어/모듈을 재 배포하고자 하는 경우에도 필자의 허락을 얻어야 합니다.

Implementation Overview

HTTP 모듈이라 함은 ASP.NET의 기본 처리 과정에서 HTTP Request가 처리 되기 전에 수행되는 필터 혹은 전처리/후처리를 수행할 수 있는 ASP.NET의 인프라이다. ASP.NET이 제공하는 Cookie-less 세션 기능, Form 인증 등이 모두 HTTP 모듈을 통해 구현되고 있다. HTTP 모듈은 다양한 방면에서 유용하게 써먹을 수 있으므로 다음에 상세히 이빨을 까기로 하고, 여기서는 필자가 작성한 HTTP 압축 기능이 ASP.NET의 HTTP 모듈로 작성되었다는 것만 알아 두면 되긋다.

HTTP 모듈은 System.Web.IHttpModule 인터페이스를 구현하는 클래스이다. 필자의 HttpCompress.CompressModule 클래스는 IHttpModule 인터페이스를 구현하는 클래스로서 HTTP Request가 수행될 때마다 수행되는 BeginRequest 이벤트에서 압축 필터를 Request에 설치한다.  필터라 함은 HttpResponse 클래스의 Filter 속성에 Stream 객체를 할당하는 작업으로써, HttpResponse 객체에 쓰여지는 모든 데이터가 Filter 속성에 지정된 스트림을 통하게 된다는 것이다. 따라서 이 Filter 속성에 압축을 수행하는 Stream 객체를 할당하면 압축이 수행되게 되는 것이다. (원리는 간단하다... -_-) 대략 귀차니즘 때문에 상세한 코드 설명은 생략... (난중에 소스 공개할 때 같이 설명하거나 HTTP 모듈을 통한 필터링을 꼭지로 별도 포스트를 해볼까 한다... 기다리진 마라... 필자가 워낙 게을러서리... 아~흐~)

Installation

압축 파일을 디비보면 달랑 HttpCompress.dll 하나만 나온다. 요 DLL을 웹 어플리케이션의 bin 폴더에 복사한다. 그리고 web.config에 HTTP 모듈에 관련된 설정을 다음과 같이 집어 넣는다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<appSettings>
   
<!-- 압축 설정 :
           Content-Type과 압축할 Http Response의 크기를 설정한다.
           다음 예제 설정은 Content-Type이 text/html 과 text/xml 이며 그 크기가 8KB 이상 인 경우만
           압축을 수행한다.
    -->

    
<add key="CompressContentTypes" value="text/html:text/xml" />
    <
add key="CompressThreshold" value="8KB" />
  </
appSettings>    
  
<system.web>
    
<httpModules>
        
<add name="HttpCompress" type="HttpCompress.CompressModule, HttpCompress" />
    </
httpModules>
    
<!-- 이하 다른 부분 생략 -->
  
</system.web>
</configuration>

먼저 <system.web> 요소의 <httpModules> 요소에 HTTP 모듈을 설정을 추가한다. 위 예제는 HttpCompress.dll 을 bin 디렉토리에 복사하는 경우의 예제이며, HttpCompress.dll을 GAC에 추가할 때는 HttpCompress 어셈블리의 버전, publictoken 등(어셈블리 Strong Name:: HttpCompress, Version=0.9.0.0, Culture=neutral, PublicKeyToken=9dc9c6c30d305b4e)을 명시해 주어야 한다.

다음은 <appSettings>에 HttpCompress 모듈이 압축을 수행할 조건을 명시해야 한다. CompressContentType 은 압축을 수행할 Content-Type을 명시한다. 위의 예에서는 일반 HTML 문서의 Content-Type과 XML 문서(웹 서비스)의 Content-Type인 text/html 과 text/xml 인 경우에만 압축을 수행하도록 설정하고 있다. 아직은 * 와 같은 와일드 카드는 지원하지 않는다. -_-

CompressThreshold 설정은 여기서 주어진 크기 이상의 Response 일 때만 압축을 수행하도록 설정한다. 필자의 테스트상 작은 크기의 컨텐츠를 압축하면 압축하는데 소요되는 오버헤드가 네트워크 상에서 얻는 잇점보다 커져서 오히려 성능에 도움이 되지 않았기 때문이다. 따라서 8-12KB 정도로 설정해 두면, 이 보다 큰 크기의 컨텐츠만이 압축되게 된다. 이 설정에 대한 절대적으로 적절한 값은 없다. 웹 어플리케이션과 사이트마다 웹 서버의 CPU 개수, 기타 네트워크 상황등을 고려하여 설정해 주어야 한다. 네트워크 사정이 상대적으로 좋은 환경이라면 이 값을 크게 잡는 것이 좋고 네트워크 사정이 좋지 못하다면 이 값을 낮게 잡아주는 것이 좋다.

이렇게 설정하면 설치가 완료된다. (이 얼마나 간단한가 !!! 아니면 말고... -_-) 이제 웹 어플리케이션이 재시작되면 (web.config를 수정했으니 재 시작될 것이다) Fiddler나 기타 다른 방법을 통해 컨텐츠가 압축되는가 확인해 보자.

Consideration

필자가 작성한 HTTP 압축 모듈은 ASP.NET의 HTTP 모듈로서 작성하였다고 하였다. 여기에 많은 함축적인 의미가 포함된다. 첫째로, 이 모듈은 오직 ASP.NET에 의해 처리되는 컨텐츠 만을 압축한다. 따라서 ASP.NET에 의해 처리되지 않는 PHP, ASP 나 정적 컨텐츠들(htm, xml 파일 등)은 비록 Content-Type이 설정에서 명시되어 있더라도 압축되지 않는다. ASP와 같은 비 닷넷 스크립트를 압축하고자 한다면 HTTP 모듈이 아닌 ISAPI 필터로 압축을 구현해야 함을 기억하자. (요거 구현이 절라 빡시다. 필요하면 돈주고 사라. 별로 비싸지도 않드라...)

둘째로, ASP.NET의 HTTP 모듈은 웹 어플리케이션 별로 적용된다. 따라서 웹 어플리케이션에 필자의 HttpCompress 모듈이 설치되면 웹 어플리케이션의 모든 컨텐츠에 대해 압축이 적용된다. 즉, 디렉토리 별로 압축 여부를 설정할 수 없다. 물론 HttpCompress 모듈이 디렉토리별로 설정을 읽어 압축 여부를 결정하도록 구현할 수도 있다. 아쉽게도 필자에게 아직 이 부분을 구현할 시간적 여유가 없었다.

세째로, 필자의 HTTP 모듈은 ASP.NET의 Output Cache를 지원한다. (뭐 사실 지원하고 싶어서 지원한건 아니고... 걍 만들다 보니 지원이 되었다. -_-) 필자가 테스트 한 결과 Output Cache가 설정된 aspx, asmx 에 대해 압축이 수행되었고, 압축된 컨텐츠는 Output Cache에 의해 훌륭하게(?) 캐시가 된다.

Recommendation

필자의 압축 모듈이 유용하다고 판단되어 실제로 적용하고자 한다면, 필자의 다음 권고를 고려해 보기 바란다.

첫째, 웹 사이트가 정적 컨텐츠 보다 동적 컨텐츠(.aspx, .ascx 등)가 더 많은 경우, 압축 모듈은 효과를 볼 수 있다.

둘째, 웹 브라우저를 수행하는 최종 사용자까지의 네트워크 회선이 10Mbps 정도로 초고속(100Mbps)이 아닌 경우 압축은 효과를 본다. 모든 사용자가 100Mbps 이상의 대역폭을 갖는다면 압축의 효과는 미비하거나 역 효과가 나타날 수도 있다. 하지만 다수의 사용자가 10Mbps 이하의 대역폭을 사용한다면 압축은 효과를 볼 것이다.

Update 2007-01-12
100Mbps 의 초고속 네트워크를 사용하더라도 다수의 사용자에 의해 네트워크 회선이 병목을 일으킨다면 콘텐트 압축은 충분한 효과를 낸다.

셋째, 정적 컨텐츠의 압축은 필자의 압축 모듈에 의해 압축되지 않기 때문에 IIS 6.0의 정적 컨텐츠 압축을 이용하는 것이 좋다. IIS 6.0의 정적 컨텐츠 압축은 압축된 파일을 캐시하므로 효율이 매우 좋다. 어떤 압축 기법(제품, 모듈...)을 사용하더라도 정적 컨텐츠의 압축은 IIS 6.0이 효율적으로 수행해 준다.

넷째, 동적 컨텐츠가 작은 조각들로 구성된 경우, 압축의 효과는 미비하다. 예를 들어, 다수의 IFRAME과 FRAME으로 구성된 웹 페이지는 상대적으로 작은 컨텐츠들이 여러 번 서비스되므로, HTTP 압축이 각각 작은 컨텐츠를 압축하게 되어 성능 상의 잇점을 많이 누리기 어렵다. 반면 단일 페이지가 100KB 이상의 HTML 을 렌더링 한다면 압축 모듈의 효과는 크다.

다섯째, 웹 서버의 CPU 사용률이 높은 편이라면 압축을 사용하지 않거나, 굳이 사용해야 한다면 웹 서버의 CPU를 더 추가해 주거나(Scale-up) 웹 서버를 추가(Scale-Out)해야 한다. HTTP 압축 모듈을 사용함으로써 더 많은 CPU 자원이 소요되기 때문에, 이미 CPU 사용률을 높은 웹 서버는 추가의 부하를 감당할 수 없을 수도 있다. 이러한 경우에는 압축이 오히려 응답 속도를 느리게 하는 요인이 될 수 있다.

FeedBack

필자의 압축 모듈에 대한 버그 리포트나 기능 추가 사항들이 있다면 이 글에 피드백을 남기거나 메일 주기 바란다. 가능한 시간을 내어 수정하도록 하겠다. 또한 이 모듈을 사용하여 효과를 보았다면 필자에게 꼭 연락 주기 바란다.