SimpleIsBest.NET

유경상의 닷넷 블로그

HTTP 압축 (2) : HTTP 압축 작동 원리

by 블로그쥔장 | 작성일자: 2005-07-18 오전 11:38:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.
지난 포스트에선 HTTP 압축을 써야하는 이유에 대해 썰을 풀어 봤씁니다. 뭐 우리나라 같이 네트워크 인프라가 좋은 상황에선 HTTP 압축이 씨가 안먹힐 가능성이 높지만 그래도 제 생각은 HTTP 압축이 유용하다는 겁니다. 최근에 100Mbps를 사용하는 사용자들도 많아졌지만 아직도 케이블모뎀(최고 10Mbps)이나 ADSL(2-4Mbps)을 사용하는 사람도 많기 때문이죠(좀더 효과를 보려면 이미지 파일들에 대한 캐시 역시 동반되어야 하겠지만...). 그래서 꾿꾿이 씨부려 볼렵니다.

HTTP Compression (II) - Principle

요번엔 HTTP 압축이란 것이 구체적으로 어케 작동하는가를 살펴보도록 하겠다. 이런거 다 때려치고 곧바로 HTTP 압축을 사이트에 적용해 보고자 하는 사람들에겐 마니 미안타... 원리를 모르고 뎀비는 것 처럼 용감한 것이 없다(XX 하면 용감하단 말을 이런 때 쓰는거 아뉠까?). 이런거 아무런 도움 안된다...

HTTP 1.1 Protocol

HTTP 1.1 프로토콜을 명세하고 있는 RFC2616을 찬찬히 살펴보면 복잡한 설명과 긴 내용에 한숨만 나올 것이다(물론 필자도 그렇다). HTTP 압축에 관련된 프로토콜 명세는 그다지 복잡하지도 많지도 않다. 간단히 꼭 필요한 거만 설명하겠다(사실 필자가 아는 것이 그것밖에 안되므로... -_-).

HTTP 압축은 (사실 HTTP 프로토콜은 HTTP 압축이란 용어를 사용하지 않는다. Content-Coding 이란 용어를 쓰며 이 Content-Coding이 주로 압축의 용도로 사용된다고 명시하고 있을 뿐이다) 두 개의 HTTP 헤더 필드에 의해 작동한다. Accept-Encoding 헤더와 Content-Encoding 헤더가 그것인데 이 두개의 HTTP 헤더 값을 통해 클라이언트(웹 브라우저)와 서버(웹 서버)가 압축을 할 것인가 말 것인가 그리고 압축에 사용되는 알고리즘을 쑈부치는 것이다.

Accept-Encoding은 클라이언트가 웹 서버에게 보내는 HTTP Request 메시지에 명세 하는 값으로서 클라이언트가 이 헤더에 명시된 인코딩(압축)을 이해하고 디코딩(압축 해제)을 수행할 수 있다는 것을 서버에 알리는데 사용한다. 즉, 클라이언트가 압축된 컨텐츠를 받아 압축을 해제할 수 있는 압축 알고리즘을 서버에 알리는 용도로 Accept-Encoding 헤더가 사용된다. IE 6.0에서 서버에 보내는 HTTP Request 메시지를 우리의 멋진 유틸리티인 Fiddler로 살짝 디비보면 Accept-Encoding이 다음과 같이 명시 되어 있음을 알 수 있다.


Accept-Encoding: gzip, deflate
 

요 헤더 값이 의미하는 것은 IE가 gzip 그리고 deflate 인코딩, 즉 압축 알고리즘을 이해하므로 웹 서버가 HTTP Response 메시지를 이들 알고리즘 중 하나로 압축해서 보내도 된다는 것을 서버에게 찔러 주는 것이다.

웹 서버는 Accept-Encoding의 값을 살펴보고 필요에 따라서 HTTP Response(HTML, CSS, 이미지 등의 결과물)를 압축 할 수 있다. 웹 서버가 HTTP Response를 압축했다면 서버는 결과가 어떤 알고리즘에 의해 인코딩(압축) 되었는가를 Content-Encoding 헤더를 통해 명시한다. 다음은 http://www.goole.co.kr 에서 반환한 HTTP Response 헤더의 내용이다.

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Content-Encoding: gzip
Server: GWS/2.1
Content-Length: 1865
Date: Thu, 14 Jul 2005 14:21:24 GMT

구글은 Content-Encoding 헤더 값에 gzip에 명시하여, 컨텐츠가 gzip 알고리즘에 의해 압축되었음을 브라우저에게 알리고 있다.

Test

직접 테스트하여 눈으로 HTTP 압축이 수행되는 것을 살펴보자. 먼저 Fiddler를 수행시킨다. 그리고 IE를 수행시키고 http://www.yahoo.com 에 접속해 보자. 그러면 Fiddler에 IE가 전송하는 HTTP Request 헤더와 Yahoo 사이트가 반환하는 HTTP Response 헤더가 다음과 같이 표시될 것이다. 그리고 사이트가 반환하는 실제 컨텐츠(TextView 버튼을 클릭해 보라)는 HTML 이 아닌 바이너리 임을 알 수 있을 것이다. IE 브라우저가 압축을 풀고 그 결과를 표시하는 것이다.

<<IE의 Accept-Encoding 값 과 Yahoo 사이트의 Content-Encoding 값>>

이제 동일한 사이트에 대해 Accept-Encoding 을 명시하지 말아보자. Fiddler의 오른쪽 패널에서 Request Builder 탭을 선택하고 HTTP Request를 '생성'해 보자. URL 입력란에 Yahoo 사이트를 입력하고 Execute 버튼을 클릭하면 HTTP Request 가 만들어지고 이것이 수행될 것이다. 그리고 나서 HTTP Response 결과를 살펴보자. Request에서 Accept-Encoding이 명시되지 않았으므로, 웹 서버 역시 압축을 수행하지 않았음을 알 수 있다. 즉, Content-Encoding 이 명시되지 않았을 뿐더러 TextView 버튼을 눌러보면 HTML이 압축되지 않은 상태로 반환되었음을 확인하자.

<< HTTP 호출 만들기 >>

HTTP Compression Implementation

대략적으로 원리를 알아보았으니 구현을 어떻게 하면 될지 감이 잡힐 것이다. 웹 서버 구현이라면 클라이언트로부터 Accept-Encoding을 통해 클라이언트가 압축을 지원하는지 검사하고 지원한다면 컨텐츠를 압축한다. 그리고 Reponse 메시지에 Content-Encoding을 명시해 주면 될 것이다. 클라이언트의 경우, IE와 같은 브라우저를 사용한다면 이미 구현이 다 되어 있으므로 아무런 작업을 수행할 필요가 없다. 하지만 System.Net 네임스페이스의 HttpWebRequest 클래스 및 HttpWebResponse 클래스를 사용한다면 직접 구현이 필요할 것이다. HttpWebReqest 클래스에 Accept-Encoding을 명시해 주고 HttpWebResponse에서 Content-Encoding을 검사하여 압축되었다면 압축을 해제하면 된다. 다음 코드는 SharpZipLib 라이브러리를 이용하여 압축된 HTTP 컨텐츠를 압축 해제 하는 예제 코드이다.

using System;
using 
System.IO;
using 
System.Net;
using 
ICSharpCode.SharpZipLib.GZip;

class 
HttpDecompressTest
{
    
// HTTP 압축 해제 예제 코드
    
[STAThread]
    
static void Main(string[] args)
    {
        
string url "http://www.google.co.kr";

        
HttpWebRequest req (HttpWebRequest)WebRequest.Create(url);
        
// gzip 압축 허용
        
req.Headers["Accept-Encoding""gzip";

        
HttpWebResponse res (HttpWebResponse)req.GetResponse();
        string 
contentEncoding res.Headers["Content-Encoding"];
        
Stream httpStream, resultStream;
        
httpStream res.GetResponseStream();
        
// 압축 여부 확인
        if (contentEncoding == "gzip") {
            // SharpZipLib의 압축 해제 스트림 사용
            resultStream = new GZipInputStream(httpStream);
        
}
        
else {
            resultStream 
httpStream;
        
}
        
// 간단한 구현이므로 euc-kr로 하드 코딩.
        
System.Text.Encoding encoding System.Text.Encoding.GetEncoding("euc-kr");
        
// 결과 표시
        
StreamReader reader = new StreamReader(resultStream, encoding);
        
Console.WriteLine(reader.ReadToEnd());
        
resultStream.Close();
    
}
}

<< HTTP 압축 해제 예제 코드 >>

위 코드에서 Accept-Encoding을 설정하는 부분을 유심히 살펴볼 필요가 있다. 이 설정이 없는 경우 구글 사이트는 압축을 수행하지 않을 것이다. 또한 Accept-Ecoding을 설정해 놓은 상태에서 압축을 풀지 않도록 코드를 바꾸고 결과를 살펴보자. 압축을 풀지 않으면 HTML이 아닌 요상스런 문자들이 화면을 가득메우게 될 것이다.

대부분의 경우 클라이언트로 IE를 사용하기 때문에 클라이언트의 문제는 거의 없을 것이다. 사실 중요한 것은 웹 서버의 구현이다. 만약 CGI나 ISAPI Extension으로 사이트가 구성되어 있다면 압축을 어케 시도해 볼텐데, 당췌 ASP 나 ASP.NET으로 구현된 사이트에 압축을 적용할려치면 눈 앞이 답답하고 눈알이 튀어나올려고 할 것이다. 게다가 압축을 위해 기존 코드를 수정해야 한다면 더욱 미칠 노릇 아닌가?

다음 포스트에는 프로그램 소스를 전혀 수정하지 않고(당연히 그래야 할것이다) 웹 서버측에서 HTTP 압축을 수행하는 방법들에 대해 살펴보도록 하겠다. 특히 IIS 6.0의 압축 기능에 대해서 말이다. 궁금하지? 기둘리~~~



Comments (read-only)
#re: HTTP 압축 (2) : HTTP 압축 작동 원리 / 황달봉 / 2005-09-10 오전 8:22:00
오늘도 하나 건져갑니다.
하나라도 더 읽으면 하나라도 더 얻어갈것을 왜 이리 게으른지...쩝
#re: HTTP 압축 (2) : HTTP 압축 작동 원리 / 벼리 / 2006-07-18 오후 1:32:00
여기다 질문을 올려서 죄송합니다. ㅠㅠ
ASP.NET에서 PostBack 되었을때의 폼데이터는 압축이 안된상태로 올라가는거져?
10k짜리 aspx페이지를 3k로 압축해서 받았을 경우(대부분의 사용이 viewstate라고 가정했을때), 버튼을 눌러 postback 되면 10k의 viewstate 데이터가 그대로 올라가는 건지 ??
#re: HTTP 압축 (2) : HTTP 압축 작동 원리 / 벼리 / 2006-07-18 오후 1:32:00
여기다 질문을 올려서 죄송합니다. ㅠㅠ
ASP.NET에서 PostBack 되었을때의 폼데이터는 압축이 안된상태로 올라가는거져?
10k짜리 aspx페이지를 3k로 압축해서 받았을 경우(대부분의 사용이 viewstate라고 가정했을때), 버튼을 눌러 postback 되면 10k의 viewstate 데이터가 그대로 올라가는 건지 ??
#re: HTTP 압축 (2) : HTTP 압축 작동 원리 / 블로그쥔장 / 2006-07-18 오후 6:05:00
안녕하세요...
PostBack 시에 데이터의 압축 여부는 IE 브라우저의 설정입니다.
따라서 IE 브라우저에서 압축 여부 설정에 따라 달라질 것입니다.
대개의 경우(디폴트) IE 브라우저에서 POST 수행시 압축은 수행하지 않는 것으로 알고 있습니다.
그리고, IE에서 POST 시 압축을 수행하도록 하는 설정은 저도 아직 모른답니다.
알고 계시거나 알게 되시면 저도 꼬옥 알려주세요... -_-;