본문 바로가기

프로그래밍

웹사이트 성능 개선을 위한 gzip 압축 적용 : Apache, Tomcat, Weblogic과 Servlet Filter

웹사이트 성능 개선을 위해 gzip 압축 전송 적용하기

유닉스 압축 프로그램 gzip

gzip 은 유닉스에서 태어난 오픈소스 압축 프로그램 입니다. 알집이나 7zip 에서 사용하는 것과 동일한 Deflate 압축 알고리즘을 사용하지만 하나의 파일만 압축할 수 있기 때문에 주로 tar 프로그램과 함께 사용하곤 합니다. 불편하기 짝이없어 보이는 gzip 압축 프로그램에 주목해야 하는 이유는 gzip 압축이 웹사이트 성능 개선과 밀접한 연관이 있기 때문입니다.

 

gzip으로 압축해서
속도를 높이자

gzip을 사용한 텍스트 압축

gzip은 텍스트 파일을 압축하는데 있어서 최상의 성능을 내는 것으로 알려져 있습니다. 우리의 웹사이트는 이미지를 제외한 대부분이 텍스트 콘텐츠로 구성되어 있습니다. 자바스크립트, HTML, CSS, JSON 등 사이트를 구성하는 거의 모든 요소가 텍스트 콘텐츠 입니다.

gzip 압축 효율 (구글)

우리가 사용하는 대부분의 브라우저는 이미 gzip 압축프로그램을 내장하고 있습니다. 게다가 자동으로 gzip 으로 압축된 파일을 해제하는 기능도 탑재하고 있습니다. 즉, 서버에서 gzip 으로 압축된 형태의 텍스트 리소스가 내려오면 브라우저는 자동으로 gzip 압축을 해제하여 페이지를 표시합니다.

 

사실 gzip 인코딩 기능은 HTTP/1.1 명세에 포함되어 있으며 HTTP/1.1 을 지원하는 대부분의 현재의 브라우저는 gzip 으로 압축된 콘텐츠를 사용 가능합니다.

웹사이트 성능 개선

시스템의 응답속도는 웹사이트의 성능을 측정하는데 있어서 중요한 요소 중 하나입니다. 특히나 페이지의 초기 로딩 속도는 접속한 사용자 경험에 매우 큰 영향을 주게 됩니다. 첫화면부터 느려 터진 사이트를 참아줄만큰 착한 사용자는 국내에서 찾기 힘들다고 보아야 합니다. 

 

3초 넘어가면 ㅈ 되는것은 국룰

웹 사이트 응답속도 개선에 있어 가장 먼저 적용을 고려해야 하고 또 적용 이후에도 즉각적인 효과를 볼 수 있는 가장 탁월한 수단이 바로 gzip 압축전송의 적용입니다. 웹서버에 간단한 설정만으로 적용이 가능하고 별다른 사이드 이펙트를 찾기도 어렵습니다. gzip 압축이 영향을 주는 구간이 웹서버와 사용자 브라우저 사이의 네트웍 구간이기 때문에 프로그램의 실행 로직등에는 영향을 주지 않기 때문입니다.

 

gzip 압축 전송을 이용하면 사이트 트래픽의 대부분을 점유하는 Big 3 (자바스크립트, CSS, HTML) 요소를 크게는 90% 가까이 압축하여 전송할 수 있기 때문에 네트웍 대역폭 사용량을 크게 감소시킬 수 있습니다. 

gzip 압축을 적용하는 4가지 방법

사이트에 gzip 압축을 적용하는 방법은 응답할 데이터를 압축하는 작업을 누가 처리하도록 하느냐에 따라서 크게 4가지로 구분 할 수 있습니다.

  1. Apache 나 Nginx 등 Web서버에서 처리하기
  2. Tomcat 이나 Weblogic 등 어플리케이션 서버(Was)에서 처리하기
  3. Servlet Filter 를 등록하여 처리하기
  4. 정적인 파일을 미리 gzip 으로 압축하여 올리기

일반적으로는 Web 서버에서 처리하도록 하고 있으나, 프로젝트나 사이트의 사정에 따라서는 다른 방법을 고려할 수 도 있습니다. 가령 Web서버와 Was 구간의 대역폭을 확보해야 한다거나 하는 이유로 말이죠.

Apache 에 gzip 설정하기

Apcahe 웹서버 설정파일인 httpd.conf 파일에서 gzip 압축을 위한 모듈 사용을 확인합니다.

LoadModule deflate_module modules/mod_deflate.so

아래 설정은 이미지를 제외한 모든 텍스트 콘텐츠를 압축하는 설정의 한 예입니다.

<Location />
	SetOutputFilter DEFLATE

	# 오래된 브라우저는 압축 적용 안하기
	BrowserMatch ^Mozilla/4 gzip-only-text/html
	BrowserMatch ^Mozilla/4\.0[678] no-gzip
	BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

	# 압축 제외대상 지정
	SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|bmp|zip|t?gz|7z)$ no-gzip dont-vary
	Header append Vary User-Agent env=!dont-vary
</Location>

Tomcat 에 gizp 설정하기

웹서버에 압축적용이 어렵다면 WAS 서버의 설정을 이용하여 응답 데이터를 압축할 수 있습니다. Tomcat 7 버전부터 gzip 압축 설정을 지원하고 있습니다. Tomcat 서버 설정파일인 server.xml 에 선언된 HTTP Connector 설정을 찾습니다.

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

Connector 설정에 gzip 압축설정을 추가합니다.

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"
    compressableMimeType="text/html,text/plain,text/css,text/javascript,application/javascript" 
    compression="on" 
    compressionMinSize="2048" 
/>
  • compressableMimeType : 압축 적용 대상 MIME 타입을 콤마로 구분하여 지정합니다.
  • compression : gzip 압축 기능을 on / off 시킵니다.
  • compressionMinSize : 압축에서 제외할 최소 데이터 사이즈를 바이트로 지정합니다.

Weblogic 에 gzip 설정하기

Weblogic 은 12.2.1 버전부터 gzip 압축 설정을 지원하고 있습니다. Weblogic 컨테이너의 Domain 단위에 일괄로 적용하거나 weblogic.xml 파일의 설정으로 Application 단위로도 설정이 가능합니다. 아래는 gzip 압축설정을 Application 단위로 적용하는 weblogic.xml 설정 예 입니다.

<weblogic-web-app>
   <container-descriptor>
      <gzip-compression>
         <enabled>true</enabled>
         <min-content-length>4096</min-content-length>
         <content-type>text/html</content-type>
         <content-type>text/css</content-type>
         <content-type>text/plain</content-type>
         <content-type>text/javascript</content-type>
         <content-type>application/javascript</content-type>
      </gzip-compression>
   </container-descriptor>
</weblogic-web-app>

Servlet Filter 로 gzip 적용하기

사용중인 Web, Was 서버에 압축설정을 적용하기 어려운 상황이라면 J2EE 스팩인 서블릿 필터를 사용하여 응답을 압축할 수 도 있습니다. Gzip 압축을 응답에 적용하는 필터를 직접 만드는 것도 가능하겠지만 github 에 올라온 프로젝트가 있어 소개해 봅니다. 

 

 

ziplet/ziplet

ziplet. Contribute to ziplet/ziplet development by creating an account on GitHub.

github.com

 

Maven 을 사용하고 있다면 아래 의존성을 POM.xml 파일에 추가합니다. Maven 을 사용하고 있지 않다면 해당 jar 파일을 Maven Central 사이트에서 내려받아 WEB-INF/lib 폴더에 직접 복사합니다.

    <dependency>
        <groupId>com.github.ziplet</groupId>
        <artifactId>ziplet</artifactId>
        <version>2.4.1</version>
    </dependency>

 

web.xml 파일에 서블릿 필터와 필터 매핑정보를 추가하면 적용이 완료됩니다.

<filter>
	<filter-name>CompressingFilter</filter-name>
	<filter-class>com.github.ziplet.filter.compression.CompressingFilter</filter-class>
	<init-param>
		<param-name>includeContentTypes</param-name>
		<param-value>text/html,text/plain,text/css,text/javascript,application/javascript</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>CompressingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>    

자세한 설정법은 프로젝트 github 페이지를 참고해 주세요.

gzip 으로 미리 압축한 파일 사용하기

위에서 언급한 gzip 압축 전송의 단점을 구지 찾자면 모든 트래픽에서 gzip 압축을 위해서 서버의 CPU 와 메모리를 사용하게 된다는 점 입니다. 네트워크 대역폭에서 이득을 얻는 대신에 비싼 서버 리소스를 조금 더 사용하게 되는 것이지요. 이러한 서버 자원 사용도 아깝다 싶으면 미리 정적인 텍스트 파일을 gzip 으로 압축하여 관리하는 방법도 있습니다. 

gzip -f *.js

압축 대상파일을 gzip 명령으로 압축해야 하고 실제 js 파일을 사용하는 소스도 수정이 필요한 번잡스러움이 존재합니다. 빌드 배포과정에서 이러한 과정이 자동화 되도록 하여 휴먼 에러를 줄이는 방안이 필요합니다.

<script type="text/javascript" src="./uil.js.gz"></script>

Apache 등 웹서버의 응답헤더를 확인하여 MIME 타입 오류가 발생하는 경우는 웹서버 설정을 변경하여 압축된 gz 파일에 대한 Content Type 헤더가 올바른지 확인해야 합니다.

<files *.js.gz>
    ForceType application/javascript
    Header set Content-Encoding "gzip"
</files>

압축결과 확인

실제로 gzip 압축이 정상적으로 적용되었는지 여부는 브라우저의 개발자 도구에서 간단하게 확인이 가능합니다. 먼저 응답 헤더의 Content-Encoding 헤더 값이 gzip 으로 설정되었는지 확인 합니다. 또 개발자 도구에서 전체 Contents 의 사이즈와 실제 전송된 사이즈를 비교해 보면 압축 효율도 확인이 가능합니다.

 

응답 헤더의 Content-Encoding: gzip

 

크롬 개발자 도구의 Network 탭의 옵션 설정에서 Use large request rows 기능을 활성화 하면 각 요청 별로 실제 Contents 의 사이즈와 압축되어 전송된 사이즈의 비교가 가능합니다.

 

개발자 도구의 Use large request rows 옵션 활성화
각 요청별로 실제 사이즈와 압축된 사이즈 비교가 가능