본문 바로가기
APM

웹 성능 향상 개발 방법(YSlow)

by 누피짱 2008. 4. 25.

1. Make fewer HTTP requests
 - 사용자 응답시간의 80%는 프론트앤드단에서 발생한다. 많은 시간을 페이지의 컴포넌트(이미지, css, script, flash등)를 다운받는데 쓰인다는 얘기다. 위의 컴포넌트는 각각의 http request를 유발시켜서 페이지를 느리게 한다.
 - Image Maps - 이미지 맵은 하나의 이미지로 여러장의 이미지 효과를 나타낸다. 또한 같은 사이즈를 가지고 많은량의 http request를 줄여준다.
 - Css Request - 이미지맵처럼 필요한 이미지를 한장에 담고 css 스타일 적용으로 필요한 부분만 보이게 한다.
 - Inline Images - data:URL scheme를 이용하여 페이지에 이미지 데이터를 삽입시킨다. 따라서 html 페이지의 사이즈는 엄청 커지는데 반해 요청은 줄게 된다.
 - Comblined Files - 스타일시트, 스크립트 파일을 모두 통합하여 하나의 파일에 포함시켜 http request를 줄인다.

2. Use a CDN(Content Delivery Network)
 - CDN 서비스라고 하면 사용자의 위치에 따라서 가장 가까운 서버에 접속해서 데이터를 가져오는 서비스를 말한다. 데이터를 가장 빠르게 받을수 있는 서버에서 데이터를 받는다면 당연히 페이지가 빨리 뜰것이다.  야후의 경우 약 20%정도의 성능향상이 있었다고 한다.

3. Add an Expires header
 - 웹페이지가 점점더 richer해지면서 각종 script, css, images등이 증가 하게 되며 이는 많은 http request를 유발시킨다. 하지만 expire header를 추가 한다면 이것들을 캐싱시킬수 있다.
 - Expire header를 사용하면 그 날짜가 지나기 전에는 각 컴퍼넌트를 재 호출하지 않는다. 만약 아파치서버를 사용중이라면 ExpireDefault값을 이용하여 지정을 해줄수 있다.
- [Apache에서 사용 방법]

<IfModule mod_expires.c>
    ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>
or
<IfModule mod_expires.c>
    #ExpiresByType image/gif A2592000
    #ExpiresByType text/css A2592000
    #ExpiresByType application/x-javascript A2592000
    #ExpiresByType image/jpeg A2592000
# 제외할 디렉토리
#<Directory "/usr/local/apache/htdocs/temp">
#ExpiresActive Off
#</Directory>
#</IfModule>
4. Gzip Components
 - 원초적인 해결방법으로 대역폭이나 캐싱가지고 해결이 안된다면 압축을 하는 방법도 있다. 즉 http request(1.1)의 헤더에 accept-encoding헤더를 붙여서 보내면 서버는 압축을 하며, 지정된 엔코딩 방식으로 압축후 response할때 그 엔코딩 방식으로 같이 붙여서 보내며, 이를 브라우저가 해석하는 방식이다. (가장 많이 쓰이는것이 gzip방식)
 - gzip의 경우 약 70%의 압축률을 보여주며, 현재 90%의 인터넷 브라우저가 gzip을 지원한다. 다만 압축방식의 경우 image와 같은 이미 압축이 되어있는 파일을 대상으로 할경우에는 오히려 사이즈가 더 커지는 문제가 있으므로, script같은 text로 이루어져있는 컴포넌트 같은경우 매우 효율적일 수 있다.
 - [apache - mod_deflate ]
AddOutputFilterByType DEFLATE text/html text/plain text/xml
<Location />
# 필터를 추가한다
SetOutputFilter DEFLATE
# Netscape 4.x에 문제가 있다...
BrowserMatch ^Mozilla/4 gzip-only-text/html
# Netscape 4.06-4.08에 더 문제가 있다
BrowserMatch ^Mozilla/4\.0[678] no-gzip
# MSIE은 Netscape라고 자신을 알리지만, 문제가 없다
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# 주의: 아파치 2.0.48까지 mod_setenvif의 버그때문에
# 위의 정규표현식은 동작하지 않는다. 원하는 효과를
# 얻기위해 다음과 같이 수정하여 사용한다:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
# 이미지를 압축하지 않는다
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
# 프록시가 잘못된 내용을 전달하지않도록 한다
Header append Vary User-Agent env=!dont-vary
</Location>
5. Put CSS at the top
 - 야후의 조사에 따르면 스타일시트를 웹페이지의 head 태그 안에 넣는것 만으로도 좋은 성능을 낸다고 한다.

6. Move scripts to the bottom
 - <head> 대신 <body> 아래쪽에 스크립트를 넣는다.

7.  Avoid CSS expressions
 - CSS expression을 피하라 : width: expression(~~~) 식의 표현을 자제하면 된다.

8. Make JS and CSS external
 - 자바스크립트와 CSS를 외부로 빼내라

9. Reduce DNS lookups
 - DNS lookup시간을 줄여라

10. Minify JS
 - 스크립트의 사이즈를 최소화하라
 - js, css 파일을 압축 : 다른 리소스들(이미지와 같은)은 http connection이 모두 사용되어 다운로드를 하지만 유독 js만은 하나의 커넥션으로만 진행됨
  : 압축 해주는 사이트 : http://alex.dojotoolkit.org/shrinksafe/
  : java -jar custom_rhino.jar -c all.js > all_comp.js 2>&1
  : 캐싱되는 문제점을 보완하기 위해서 <script src="script1.js?v=001"></script> 식으로 js src 지정자를 변형시킵니다.
 
11. Avoid redirects
 - 리다이렉트 페이지를 피하라

12. Remove duplicate scripts

 - 중복 스크립트를 제거 하라.

13. Configure ETags
  - ETag는 HTTP/1.1 에 명시되어있는 response header로서, cache validation으로 사용될 수 있는 값을 나타낸다. caching을 수행하는 측에서는 If-Modified-Since로 validation - caching되어있는 object가 새로 갱신하지 않아도 되는 유효한 object 인지 확인하는 작업 - 을 수행할 때, 저장되어있던 ETag값을 같이 이용하여 좀 더 확실한 validation을 할 수 있다.
 문제는, 아파치의 경우 ETag값을 파일의 i-node, size, last-modifed time (mtime) 을 이용하여 계산한다는 것이다.
 만약 아파치 웹서버들이 Round-Robin 방식으로 클러스터를 구성하면 웹서버들마다 같은 파일이라도 다른 i-node 값을 갖게될 가능성이 매우 크므로, caching을 수행하는 측의 cache hit-ratio가 매우 떨어지게 된다.
 이 문제를 해결하기 위해서는 아파치가 ETag를 계산하는 방식을 바꿈으로써 각 웹서버들마다 같은 파일에 대하여 같은 ETag 값을 보내주도록 한다. 아파치의 FileETag directive를 사용하여 다음과 같이 한다.
<Directory /www/test>FileETag MTime Size </Directory>
 FileETag directive는 아파치가 ETag를 계산할 때 파일의 어떤 속성값들을 사용할지를 지정한다. 위와 같이 last-modified time과 size 속성값만을 사용하여 ETag를 계산하도록 하면, 같은 파일에 대하여 여러 웹서버들마다 동일한 ETag값이 계산되도록 할 수 있다.
 단, FileETag directive는 아파치 1.3.23 이후부터 지원되는 directive 이다. 이전버젼들에 대해서 사용하고 싶을 경우는 아파치 소스를 수정하여 사용할 수 밖에 없을 것이다. (아파치 모듈로 해결가능한지는 확인해보지 않았다.)

댓글