안녕하세요... 블로그 쥔장입니다. 모든 어플리케이션에서 그러하듯이 성능 문제는 항상 개발자를 따라다니는 골치아픈 요소 중 하나입니다. 그래서 기획 포스트로 HTTP 압축 씨리즈를 써 볼까 합니다. 일반적인 성능 향상 기법인 데이터베이스 튜닝이나 어플리케이션 튜닝 측면이 아닌 다른 측면에서 접근해 보고자 하는 것이지요. 많은 성원 바랍니다... ^^

HTTP Compression (I) - Introduction

최근 필자가 관여한 프로젝트는 성능 문제가 한참 이슈로 떠오르고 있다. 프로젝트 초기 시점만 해도 주어진 개발 기간 내에 개발 완료가 가능한지 불투명한 상태였는데, 이제 개발 기간 내에 개발을 완료하고 나니 성능에 대해 이러쿵 저러쿵 이야기를 하는 것이였다. 완저니 물에 빠진 사람 살려놓으니 보따리 내놓으라는 격이 아닌가... (쓰봉.... -_-)

사실 어플리케이션의 성능은 문제가 없었다 (적어도 현재까지는). 다만... 원격 사용자가 느린 네트워크 상(512Kbps 미만)에서 어플리케이션에 접근하는데 원하는 성능(3초내 결과 표시)이 나오지 않는다는 불만이다. 사실 UI 화면은 많은 데이터를 표시하고 있어서 웬만한 화면은 1회 조회에 수백 킬로바이트(400건에 1MB가 넘는 경우도 있다...)의 XML 데이터를 웹 서버로부터 다운로드 받아야만 한다. 이런 느린 네트워크 상에서 아무리 데이터베이스를 튜닝하고 어플리케이션 코드를 튜닝해 봤자 성능 이야기는 남의 나라 얘기가 되고 만다. 똥인지 된장인지 찍어 맛봐야 아나?

Generic Performance Tuning

어플리케이션 성능 향상을 위해 수행하는 튜닝 기법은 매우 다양하다. 하지만 아주 많은 경우 데이터베이스 튜닝으로도 많은 성능 향상을 기대할 수 있다(코드에서 웬만한 삽질만 안 하면 DB 설계/튜닝만 잘해도 성능 잘 나온다). 필자의 경험으로도 그러하거니와 대다수의 프로젝트에서 성능을 저하시키는 병목 현상은 데이터 베이스에서 발생하곤 한다. 잘못 설계된 데이터 모델, 잘못된 인덱스나 부족한 인덱스, Lock-intension, 잘 구성되지 못한 SQL 쿼리 문장, 너무 많은 트리거 등등이 주된 데이터베이스 튜닝 포인트이다. 더 이상 묻지 마라. 필자의 전문영역 아니다. -_-

데이터베이스 튜닝이 완료되면 성능 향상을 기대할 수 있으며 실제로 성능이 향상된다. 하지만 데이터베이스가 빠르게 결과값을 토해 냄에도 불구하고 성능이 안나오는 경우도 종종 있는데, 이 때 필요한 것이 어플리케이션 튜닝이다. 어플리케이션 성격과 맞지 않는 시스템 아키텍처 혹은 어플리케이션 아키텍처, 잘못 사용하는 COM+ 모델(Server 모드 쓰면 쥐약이다), 잘못된 COM+ 코딩 패턴(SetComplete 안하거나 Dispose 안해 준다든가 등등), 불필요한 트랜잭션 코드(단순 조회에 트랜잭션 건다든가...), 불필요하게 많은 서버와의 통신(한 화면에 서버를 댓번씩 왔다 갔다하는 코드), 너무 많은 ASP.NET 서버 컨트롤 등등이 기술적 관점에서 어플리케이션 튜닝 포인트로 볼 수 있다. 한편 비효율적인 업무, 잘못 설계된 화면, 너무 복잡한 화면 구성, 비효율적인 데이터 처리 등이 업무적 관점에서의 어플리케이션 튜닝 포인트이다(요거 현업은 절대 양보 안 할라구 한다. 절라 열받게도 업무가 삽질인데 시스템으로 커버 할려는 무식한 동물들이 있다. 주위에 이런 짐승들이 보이면 곧바로 가까운 동물원에 신고해라...).

데이터베이스 튜닝및 어플리케이션 튜닝과 동시에 수행되어야 할 부분이 있다면 웹 서버 시스템 자체에 대한 추가적인 튜닝이다. Windows 운영체제 최적화, 캐시 설정, IIS 성능을 위한 설정 등등... 하지만 필자의 경험상 Windows 2003 운영체제와 IIS 6.0은 데이터베이스와 어플리케이션 코드가 잘 작성되어 있다면 별도의 튜닝을 필요로 하지 않을 정도로 충분히 효율적이다(꼭 코드 이상하게 해놓고 Windows 하고 IIS/COM+ 핑계 대는 사람들이 있다).

Other Approach

이러한 일반적인 튜닝을 거쳤다면 대부분의 어플리케이션의 성능은 문제가 없을 것이다. 필자가 말하고 싶은 것은 이것이 아니다. 데이터베이스, 웹 서버 등이 최적의 상태로 최고의 성능을 내도록 작동하고 있음에도 불구하고 고객으로부터 성능에 대한 불만은 나올 수 있다는 점이다. 예를 들어 데이터에 비해 네트워크 대역폭이 충분하지 않다던가, 클라이언트 PC가 너무 노후되어 있다던가 하는 문제는 데이터베이스 튜닝이나 어플리케이션 튜닝으로는 해결하기 어려운 성능 문제이다.

필자가 부딪혔던 성능 문제도 바로 이런 것이였다. 필자가 관여된 어플리케이션은 다량의 데이터를 조회하는 화면이 많다. 수백 건의 데이터를 한번에 조회하는 것은 다반사요, 3만건 이상의 데이터를 한번에 조회하여 보는 업무도 있다(신고해도 안 잡아 가드라...). 본사 건물은 100Mbps의 충분한 대역폭을 갖고 있기 때문에 충분한 성능을 제공한다. 하지만 소위 '현장'(건설 현장, 파견 사무소 등을 생각하믄 된다) 같은 곳에서는 평균적으로 2Mbps의 네트워크의 xDSL을 사용하고 있으며 심한 경우에는 500Kbps 도 안 나오는 네트워크 라인을 수십 명이 공유하고 있는 곳도 있었다. 이렇게 네트워크 대역폭이 충분하지 못한 경우에는 데이터베이스 서버와 웹 서버가 아무리 번개 같이 결과값을 뿜어대도 데이터가 네트워크를 타고 클라이언트까지 도착하는 데는 하세월이 걸려 버린다. (본사에서 0.5초 만에 결과가 나오는 화면이 현장에서 40초가 넘게 걸리는 경우도 있었다 !)

물론, 네트워크 대역폭을 늘리면 된다고 쉽게 생각할 수도 있지만 네트워크 대역폭을 늘리는 것은 웹 서버를 몇 대 추가하는 것 처럼 서버측 용량을 늘리는 것과는 전혀 다른 복잡한 문제들을 야기하곤 한다. 필자가 관여된 프로젝트의 경우 처럼, 기업의 인트라넷이라면 대역폭을 늘리는 것을 고려해 볼 수도 있겠지만 불특정 다수를 대상으로 하는 인터넷 웹 어플리케이션이라면 이야기가 좀 달라진다.

우리나라의 웹 사이트들은 외국 웹 사이트에 비해 컨텐츠가 무거운 편이다. 많은 이미지와 스크립트, 역동적인 컨텐츠 등으로 보기 좋은 컨텐츠임은 분명하지만 네트워크 상에서 흘러 다니는 HTML, 이미지, 스크립트 파일들은 상당히 큰 편이다. 이렇게 커다란 컨텐츠를 제공하면서 1Mbps 대역폭을 사용하는 사용자에게 대역폭을 늘이라고 말한다면 사용자는 아마 이렇게 대답할 것이다.

"조까 !" -_-

HTTP Compression

네트워크 대역폭을 늘이는 것 외에 네트워크 병목을 우회하는 방법이 없을까?

지금까지 서론이 좀 길었지만... HTTP 압축은 정확하게 이러한 문제를 해결하고자 하기 위한 방법이다. HTTP 1.1 스팩에서는 HTTP 메시지를 압축하기 위한 HTTP 헤더들을 정의하고 있는데, 그것이 Accept-Encoding, Content-Encoding 등 이다. 이 헤더에 의해 HTTP 서버(IIS나 Aapache 등)와 HTTP 클라이언트는 HTTP 메시지의 내용(HTML, 이미지 등)을 압축할 수 있는 것이다.

일반적으로 HTTP 압축을 사용하면 웹 서버의 부하는 증가한다. 압축을 수행하기 위해 보다 많은 CPU와 메모리가 필요하기 때문이다. 하지만 최종 사용자는 HTTP 압축에 의해 보다 빠른 응답 속도를 기대할 수 있다. 필자의 견해로는 최종 사용자가 느끼는 응답 속도의 향상은 항상 긍정적으로 작용하기 마련이다. 웹 서버가 부과되는 추가적인 오버헤드는 CPU, 메모리 혹은 웹 서버를 추가로 설치하는 간단한(?) 작업으로 손쉽게 극복할 수 있기 때문이다. 하지만 웹 서버와 최종 사용자를 가로막고 있는 네트워크 병목을 극복하기란 쉽지 않기 때문에 HTTP 압축에 더욱 더 관심을 가져줘야 하는 것이다.

이럼에도 불구하고 HTTP 압축을 사용하는 국내 사이트는 많지 않다. 우리나라의 네트워크 인프라가 너무 훌륭해서 충분히 성능이 나오기 때문일 것이라 생각된다(Yahoo, eBay, Amazon, Google 같은 국외 사이트의 경우에는 철저히 컨텐츠를 압축하고 있다). 하지만 외국에서 국내 사이트에 접근할 때도 그렇게 빠를까는 의심이 가는 대목이다. (사실 우리나라 사이트들은 압축, 크기, 이런거 너무 신경 안쓴다. 인터넷 강국의 면모를 과시라도 하듯이... 이러면서 성능 이야기 하면 좀 곤란하다...)

국내 네트워크 인프라가 좋다고 할지라도 HTTP 압축을 사용함으로써 얻을 수 있는 잇점은 있다고 본다. HTTP 압축을 통해 네트워크 대역폭을 절약할 수 있고 절약한 네트워크 대역폭 만큼 더 많은 사용자를 수용할 수 있기 때문이다. 또한 서버 측 네트워크 대역폭을 늘리기 위한 투자 비용 역시 줄일 수 있을 것이다.

Various Considerations

HTTP 압축이 항상 좋기만 한 것은 아니다. 해당 웹 어플리케이션을 사용하는 모든 클라이언트가 100Mbps의 충분한 대역폭을 갖는다고 한다면 HTTP 압축은 추가적인 오버헤드만을 발생할 뿐 이득을 얻을 수 없다. 하지만 클라이언트의 네트워크 대역폭이 10Mbps 이하가 된다면 HTTP 압축은 거의 항상 최종 사용자에게 응답 속도가 향상되었다는 느낌을 갖도록 할 수 있다.

구체적으로 예를 들어 보자. 웹 페이지의 크기가 HTML, 스크립트 등을 합쳐서 200KB 라고 가정해 보자. 200KB를 압축하는데 소요되는 시간은 서버 마다 다르겠지만 채 0.02초도 소요되지 않는다. 하지만 200KB를 10Mbps에서 다운로드 하는데 소요되는 시간은 아무리 빨라도 0.15초 이상이 소요된다(실제로는 0.22 초 이상 소요된다). 200KB를 압축할 때 압축율을 30%로 잡으면 다운로드할 크기가 60KB로 줄기 때문에 다운로드 속도 + 압축 소요시간 + 압축 해제 시간이 더 빠르다는 것이다.(압축을 해제하는데 소요되는 시간은 압축하는데 소요되는 시간의 1/3 정도 밖에 소요되지 않는다. 물론 이렇게 단순한 산수 연산 보다는 훨씬 더 복잡한 요소들이 성능에 영향을 준다.)

HTTP 압축을 사용하겠다고 결정을 했다면 또 주의할 사항은 어떤 컨텐츠를 압축할 것인가 신중해야 한다. 일반적으로 GIF, JPG 등의 이미지 파일은 압축하지 않는 것이 좋다. 너무도 당연한 것이 이들 이미지 포맷은 이미 압축이 되어 있기 때문에 실제 압축 해봤자 압축율이 90%를 육박한다. 따라서 이들을 압축했을 때는 오버헤드만이 증가되고 네트워크 속도에서 얻을 이익이 없기 때문이다. 일반적으로 HTML 컨텐츠(정적 htm 파일 이건 asp/aspx에 의해 동적으로 생성되었건), XML 컨텐츠, 커다란 스크립트(.js 파일) 파일 등 텍스트 컨텐츠에 대해 압축을 수행하는 것이 일반적이라 할 수 있다.

How To?

HTTP 압축이 효용이 있을 수 있다는 것에 동감했다면 어떻게 HTTP 압축을 수행할 수 있을 것인가? 여러분의 웹 어플리케이션이 어떤 상황에서 작동하고 있는가에 따라서 방법은 다르다. IIS를 제외한 상황이라면 나도 모른다. 여러분 웹 서버의 메뉴얼을 살펴보기 바란다. IIS를 사용한다면 IIS의 버전에 따라서 그리고 ASP 인가 ASP.NET 인가에 따라서 다양한 방법이 나올 수 있다. 간단히 상용 HTTP 압축 모듈을 구입해 설치하는 방법부터 IIS 6.0 부터 제공되는 HTTP 압축 기본 기능을 활용하던가, 직접 HTTP 압축 모듈을 구현할 수도 있다.

다음 포스트에서 HTTP 압축을 위한 HTTP 프로토콜의 명세 그리고 IIS 6.0이 제공하는 HTTP 압축 기능 그리고 ASP.NET 코드를 이용하여 직접 HTTP 압축 모듈을 작성하는 방법에 대해 차근 차근 몇 회의 포스트에 이어 글을 연재하고자 한다. 기대하시라~~ 개봉 박두 ! ! !