SimpleIsBest.NET

유경상의 닷넷 블로그

HTTP 압축과 .NET Framework 2.0

by 블로그쥔장 | 작성일자: 2006-06-27 오전 1:07:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

HTTP 압축에 대해서 여러 포스트에서 다뤘습니다만... .NET Framework 2.0 이 등장함에 따라 닷넷 클라이언트가 압축된 HTTP 컨텐트를 보다 쉽게 처리할 수 있게 되었습니다. 이번 포스트에서는 이러한 사항에 대해서 살펴보도록 하겠습니다.


HTTP 압축 관련글

HTTP Compression in .NET Framework 2.0

필자의 기존 포스트, HTTP 압축 (1) : 성능 향상을 위한 다른 접근 기법 에서 HTTP 압축이 왜 필요하며, 어떤 장점을 주는지 설명하였다(귀차니즘에 떠는 독자들은 쑛 잡고 반성해라. 필자가 쑛 빠지게 작성한 글, 성의가 괴씸 해서라도 읽어보는 것이 성의 아닌가?). 또한 어떻게 HTTP 압축이 작동되는 지 역시 HTTP 압축 (2) : HTTP 압축 작동 원리 이미 설명하였다. 이 글에서는 HttpWebRequest 클래스 및 HttpWebResponse 클래스를 이용하여 웹 서버를 액세스하는 닷넷 HTTP 클라이언트를 작성할 때 웹 서버가 컨텐트를 압축하는 경우 처리하는 방법에 대해서도 예제 코드까지 이용하여 상세히(?) 설명했다. 이 예제 코드는 GZip 라이브러리를 사용하여 직접 압축을 해제하도록 하고 있는데, 이는 HttpWebRequest/HttpWebResponse 클래스가 Socket 기반으로 구현되어 HTTP 압축을 전혀 이해하지 못하기 때문이였다(상세한 내용은 HTTP 압축과 웹 액세스 API 글을 참고하기 바란다).

닷넷 프레임워크 2.0에서 와서는 이야기가 전혀 달라졌다. 닷넷 프레임워크 2.0의 HttpWebRequest 클래스와  HttpWebResonse 클래스는 이제 HTTP 압축에 사용되는 Accept-Encoding 헤더를 Content-Encoding 헤더를 인식하고 스스로 압축을 해제(decompress)할 수 있는 능력을 갖게 되었다. 이제부터 상세히 살펴 보도록 하자.

AutomaticDecompression Property

닷넷 프레임워크 2.0의 HttpWebRequest 클래스는 AutomaticDecompression 속성이 추가 되었다. 이 속성의 디폴트 값은 하위 호환성을 위해 None으로 설정되어 있다. 하지만 이 속성이 GZip 혹은 Deflate로 설정되면 HttpWebRequest 객체는 HTTP Request 에 Accept-Encoding 헤더를 추가할 뿐만 아니라, HttpWebResponse 객체가 Content-Encoding 헤더를 인식하여 HTTP Response가 압축된 경우에 자동으로 압축을 해제하도록 해준다(HTTP 압축과 관련된 HTTP 헤더에 대해서는 HTTP 압축 (2) : HTTP 압축 작동 원리 포스트를 참고하기 바란다).

일단 코드를 먼저 살펴보자. 닷넷 프레임워크 1.1에서라면 다음과 같이 코드를 작성해야만 했다.

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.simpleisbest.net";

        
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.UTF8;
        
// 결과 표시
        
StreamReader reader = new StreamReader(resultStream, encoding);
        
Console.WriteLine(reader.ReadToEnd());
        
resultStream.Close();
    
}
}

리스트1. 닷넷 프레임워크 1.1에서 HTTP 압축을 처리하는 HTTP 클라이언트

리스트1과 같이 2.0 이전 코드의 문제점은 개발자가 일일이 HTTP 압축에 관련된 헤더 설정을 해야 하며, SharpZipLib 라이브러리 와 같은 압축 라이브러리를 사용하여 압축을 직접 해제해 주어야 한다는 점이다. 더욱이 압축 여부를 판단하는 등의 일부 코드는 하드 코딩까지 되어 있다.

이제 리스트1과 같은 코드는 닷넷 프레임워크 2.0에서 AutomaticDecompression 속성으로 간단히 해결가능하다. 더욱 좋은 것은 2.0에 압축 관련 클래스가 제공되기 때문에 별도의 외부 압축 라이브러리를 가져다 쓸 필요도 없어졌다.

using System;

using System.Collections.Generic;

using System.Text;

using System.Net;

 

namespace HttpDecompressTest2

{

    class Program

    {

        [STAThread]

        static void Main(string[] args)

        {

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://www.simpleisbest.net/");

            // 압축을 자동으로 처리하도록 한다. 이 경우 GZip 만을 사용하도록 했다.

            req.AutomaticDecompression = DecompressionMethods.GZip;

            HttpWebResponse res = (HttpWebResponse)req.GetResponse();

            System.IO.Stream stream = res.GetResponseStream();

 

            System.IO.StreamReader reader = new System.IO.StreamReader(stream, Encoding.UTF8);

            Console.WriteLine(reader.ReadToEnd());

            reader.Close();

        }

    }

}

리스트2. 닷넷 프레임워크 2.0에서 HTTP 압축을 처리하는 HTTP 클라이언트

리스트2에서 HttpWebRequest 객체의 AutomaticDecompression 속성을 DecompressionMethods.Gzip으로 설정한 것에 주목하기 바란다. 단순히 이 속성을 설정하는 것만으로 HTTP 압축은 자동으로 처리되게 된다. 오... 친절한 닷넷씨여...

HTTP Decompression in Web Service Client

필자의 지난 포스트, HTTP 압축 : 웹 서비스 클라이언트를 읽어 보면 웹 서비스 클라이언트가 압축을 수행하는 웹 서비스 서버와 통신하기 위해서는 상당한 삽질이 필요하다는 것을 알 수 있을 것이다. 웹 서비스 참조에 의해 생성되는 웹 서비스 프록시는 내부적으로 웹 서비스의 XML 메시지를 HTTP 프로토콜에 의해 전송하고 그 결과 메시지를 수신한다. 메시지를 HTTP 프로토콜을 통해 주고 받을 때 사용하는 클래스는 당연 빤쑤로다가 HttpWebRequest 클래스와 HttpWebResponse 클래스이다.

닷넷 프레임워크 2.0 이전에는 이들 두 클래스가 HTTP 압축에 대한 지원이 전혀 없었기 때문에 프록시 클래스를 상속하여 새로운 프록시 클래스를 만들어, GetWebRequest 메쏘드를 오버라이드 하여 Accept-Encoding 헤더를 생성해 주었다(예제 코드 링크). 어디 이 뿐인가? GetWebResponse 메쏘드도 오버라이드 해서(예제 코드 링크) 압축 해제를 수행하는 DecompressHttpWebRequest 클래스까지 사용하지 않았던가?

닷넷 프레임워크 2.0은 더 이상 이러한 삽질을 하지 않아도 된다. 웹 서비스 프록시의 베이스 클래스는 HTTP 압축을 처리할 것인가를 결정하는 새로운 EnableDecompression 속성이 추가되었다. 이 속성은 HttpWebClientProtocol 클래스에 정의 되어 있는데, 이 클래스에서 파생된 클래스가 SoapHttpClientProtocol 이며, 이 SoapHttpClientProtocol 에서 파생된 클래스가 웹 참조에 의해 생성되는 여러분의 프록시 클래스이다. 고로, 프록시 클래스의 EnableDecompression 속성의 값만 설정해 주면 HTTP 압축 : 웹 서비스 클라이언트 글에서 설명한 복잡시런 코딩을 하지 않아도 되는 것이다!

EnableDecompression 속성의 기본값은 false 이다. 뭐 하위 호환성을 위해 false로 설정했으리라 생각되므로 용서해 주자. 이 속성 값을 true로 설정하면 웹 서비스 프록시는 HTTP 압축을 하는데 필요한 작업을 수행해 준다. 정확히 말해서 내부적으로 사용하는 HttpWebRequest 객체의 AutomaticDecompression 속성의 값을 DecompressionMethods.GZip 으로 설정해주는 것이 전부지만 이 속성을 설정함으로써 웹 서비스 프록시는 웹 서비스 메시지를 압축하거나 해제(decompress)하는데 필요한 모든 작업이 수행되는 것이다.

리스트3의 예제 코드를 살펴보자. 이 코드는 필자의 사이트에 테스트로서 존재하는 웹 서비스(http://www.simpleisbest.net/apps/smartclientbasic/testservice.asmx)를 호출하는 예제 코드이다. 주의 깊게 살펴볼 부분은 프록시 클래스의 EnableDecompression 속성을 true로 설정하는 코드이다. 이 간단한 한 줄로서 웹 서비스 호출 메시지의 HTTP 헤더에는 Accept-Encoding 헤더가 포함될 것이고, 만약 웹 서비스 서버가 웹 서비스 호출 결과를 압축한다면 그것을 자동으로 압축 해제하게 될 것이다.

using System;

 

namespace HttpCompressionTest2

{

    class Program

    {

        [STAThread]

        static void Main(string[] args)

        {

            SimpleIsBest.TestService svc = new HttpCompression2.SimpleIsBest.TestService();

            svc.EnableDecompression = true;     // HTTP 압축 설정

            svc.TestWebMethod();

        }

    }

}

리스트3. 웹 서비스 프록시의 HTTP 압축 설정

EnableDecompression 속성을 true로 설정하건 false로 설정하건 그 결과는 동일할 것이므로 Fiddler 와 같은 도구를 사용하여 실제로 웹 서비스 메시지가 압축되는지 확인해 볼 필요가 있다. 싫음 그냥 필자를 믿던가... -_-

필자의 예전 HTTP 압축 : 웹 서비스 클라이언트 글을 읽어 보았던 독자라면 기존 닷넷 프레임워크 1.1 기반의 코드보다 엄청나게 간단해 졌음을 알 수 있을 것이다. 닷넷 프레임워크는 버전이 올라갈 수록 친절해 진다는 것을 뼈저리게 느끼면서 이번 포스트를 마무리 한다...



Comments (read-only)
#re: HTTP 압축과 .NET Framework 2.0 / 최재훈 / 2006-06-27 오전 9:30:00
"귀차니즘에 떠는 독자들은 쑛 잡고 반성해라. 필자가 쑛 빠지게 작성한 글, 성의가 괴씸 해서라도 읽어보는 것이 성의 아닌가?"은 잊지 못할 것 같습니다. ^^
#re: HTTP 압축과 .NET Framework 2.0 / 블로그쥔장 / 2006-06-27 오전 9:50:00
하하.... -_-;

뭐... 웃자고 해본 소리지요... 하..하.. (정말 땀나네요... -_-;)
#re: HTTP 압축과 .NET Framework 2.0 / 이경원 / 2006-06-27 오전 10:20:00
좋은 포스트 잘 읽고 갑니다..... 웹 쪽은 잘 안해봐서리^^ 웹에서 바로 압축하고 해제할 수 있네요 첨 알았습니다..^^ 좋은 포스트 감사합니다~~~
웹 구현하게 되면 함 써봐야겠어용^^ 초반의 "귀차니즘에 떠는 독자들은 쑛 잡고 반성해라. 필자가 쑛 빠지게 작성한 글, 성의가 괴씸 해서라도 읽어보는 것이 성의 아닌가?" 넘 인상적입니다... 저도 반성할 부분이 많은듯 하네요^^ 앞으로도 좋은 포스트 부탁 드립니다.... 매번 좋은 정보만 얻어가서리 죄송스럽네요^^
그럼 좋은 하루되세요~~~
#re: HTTP 압축과 .NET Framework 2.0 / 오늘 글이 올라왔군요^^ / 2006-06-27 오후 11:29:00
정말 좋은 글도 감사드립니다^^

항상 많은 도움을^^b

수고하셨습니다.
#re: HTTP 압축과 .NET Framework 2.0 / 정준명 / 2006-06-27 오후 11:58:00
아, EnableDecompression속성의 기본값이 false였군요. 어쩐지...

친절한 닷넷씨와 더불어 친절한 쥔장님 덕분에 즐겁습니다.
#re: HTTP 압축과 .NET Framework 2.0 / 위시 / 2006-06-28 오후 12:57:00
앗...^^ 드디어 새로운 포스팅이 올라왔네요..
감사합니다 일단 답글달고 읽는 센스~^^^^
#re: HTTP 압축과 .NET Framework 2.0 / 에스엠짱 / 2006-06-28 오후 8:03:00
매번 좋은글 잘읽고 배워갑니다. 감사합니다.
#re: HTTP 압축과 .NET Framework 2.0 / 워너비 / 2006-06-29 오후 8:38:00
와. 대단하군요. 정말 간단해졌네요.
좋은 글 감사합니다~!
#re: HTTP 압축과 .NET Framework 2.0 / 쥔장님 매번감사 / 2006-07-10 오전 10:50:00
얼마전 이블로그를 알고 들어왔는데...
너무나 좋은 글을 올려주셔서 감사합니다.
매번 포스트를 보면서 감탄중입니다.
많이 배우고 갑니다.~~ 꾸벅!!
#re: HTTP 압축과 .NET Framework 2.0 / 블로그쥔장 / 2006-07-10 오후 1:34:00
도움이 되셔서 저도 기쁩니다.
좀 더 자주 글을 써야 하는데... 목구멍이 포도청인지라....
죄송할 따름입니다.
#re: HTTP 압축과 .NET Framework 2.0 / 어흥이 / 2006-08-24 오후 5:19:00
정말 감사드려요.
이곳에서 너무나 많은것을 배우고 있습니다.
#re: Consider Using HTTP Compression 패턴 애인 프렉티스 익스플로어에서.. / 강희기 / 2006-11-21 오후 2:06:00
- IIS5.0에서 세팅법(닷넷1.1기준.)
: Cmd open 해서 net stop iisadmin라고치고 엔터
: cd C:\InetPub\adminscripts라고치고 엔터
: CSCRIPT.EXE ADSUTIL.VBS SET
W3Svc/Filters/Compression/GZIP/HcScriptFileExtensions "asp" "dll" "exe" "aspx"라고치고 엔터
: net start w3svc라고치고 엔터 해서 마무리..
이런 내용이 있던데 꺙 비슷한 내용이어서 적어봅니다.
글 잘읽었습니당.

#re: HTTP 압축과 .NET Framework 2.0 / 황승재 / 2007-07-27 오전 10:19:00
GOOD~~~