웹 사이트 최적화 기법
저자는 야후에서 성능 최적화 부서 팀장으로서 당장 써먹을 수 있는 내용을 많이 밝히고 있습니다.. 보통 우리가 속도가 느리면 DAO쪽에만 치중을 하는데.. 웹쪽이 느려서 기껏 빠르게 해놓은 API가 무용지물이 될수 있으니.. 웹쪽도 잘 봐두어야겠습니다.
책에서는 14가지의 규칙을 내세우며 적용하는 법을 가르켜줍니다. 하나씩 찬찬히 보도록 하겠습니다.
1. HTTP 요청을 줄여라.
=> 우리가 웹에서 URL을 치면 html을 던져주는데 html안에 이미지가 총 5개라면 총 6번의 요청이 생기게 됩니다 html(1) + 이미지(5) = 6. 음 요청이 많으면 당연히 속도가 느려지겠죠? 그럼 어떻게 HTTP 요청을 줄일 수 있을까요? 젤 쉽게 할 수 있는 방법은 이미지 큰것을 하나를 주고 그것을 CSS로 나눠서 쓰는것입니다. 이것을 CSS Sprite라고 합니다. 그래서 요청을 줄이는것이죠. 또한 스크립트와 스타일시트도 인라인으로 하나의 페이지에서 부르면 속도가 더 빠릅니다. 헌데 인라인으로 호출하면 캐쉬에 들어가지 않기 때문에 자주 호출되는 것이라면 더 느려질수도 있습니다. 'ㅡ'
단 스크립트가 너무 잘게 쪼개져 있다면 크게 하나로 합치기를 권장해드립니다.
2. 콘텐츠 전송 네트워크를 이용하라.
=> 콘테츠 전송 네트워크는 한곳에 집중되는 콘텐츠 부하를(서버 하나) 전국(지방에 몇개)으로 나누는 것입니다. 미국에 있는 야후는 미국보다 당연히 한국이 느리겠죠. 왜 일까요? 그것은 접속하는 서버가 멀리 있기 때문입니다. 이런 문제를 해결하기 위해 콘텐츠 전송 서버회사들이 생겼고 이런 회사들은 CDN(Contents delivery network)이라고 합니다 참고로 얼마전 후배녀석을 만났는데 CDNetworks라는 회사를 다니고 있더군요. 규모는 400여명이고 현재 나스닥을 준비중이라고 합니다 한국에서는 CDN관련해서는 자기 회사가 꽉잡고 있다고 하더군요. ^^(www.cdnetworks.com)
3. 헤더에 만료기한을 추가하라
=> 브라우져는 캐시를 이용하여 HTTP의 요청 수를 줄일 수 있습니다. 이때 웹서버는 헤더의 Expires 속성을 통해 브라우져가 캐시에 있는 구성요소의 복사본을 언제까지 사용할 수 있는 알려 줍니다. 자 그러면 당연히 잘 안바뀔 것 페이지는 Expires 속성을 오래두고 쓰는게 좋겠죠?
그리고 HTML/1.1에서는 Cache-Control이란것이 추가되었습니다. 이것을 이용해서 아래와 같이 캐시를 주고 안주고를 설정할 수 있습니다
보통 JSP에서는 아래와 같이 해서 캐시에 담지 않도록 하는데
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); // prevents caching at the proxy server
캐시를 준다면 아래처럼 할 수 있습니다
response.setHeader("Cache-Control","public");
response.setDateHeader(이름,날짜)="날짜(long)"를 String으로 변경하여 지정한 "이름(String)"의 헤더를 설정한다.(void)
예제로 하루를 준다면.
long lCurrentTime = System.currentTimeMillis();
long lTermTime = 60*60*24*1000 // 하루
response.setDateHeader("Expires", lCurrentTime + lTermTime);
Expires를 설정하지 않은 사이트
http://stevesouders.com/hpws/expiresoff.php
Expires를 설정한 사이트
http://stevesouders.com/hpws/expireson.php
4. Gzip 컴포넌트
=> 만약 브라우져가 압축한 파일을 인식할 수 있다면 서버에서 htrml이나 스크립트등을 압축을 해서 내려보낸다면 용량이 적으니깐 속도가 빨라지겠죠?
HTTP/1.1에서부터 웹 클라이언트(브라우져)는 Accept-Encoding 헤더를 이용해 압축의 지원 여부를 보내줍니다.
Accept-Encoding: gzip, deflate
이렇게 브라우져에서 보내주면 이 브라우져는 gzip과 deflate는 인식할 수 있구나라고 생각하고 서버에서는 아래처럼 압축을 해서보내주면 됩니다.
Content-Encoding: gzip
참고로 압축포맷에는 gzip과 deflate 두개가 있는데 gzip를 강추한다고 합니다.
그럼 무엇을 압축해야할까요?
html, 스크립트, css같은 파일은 해야할지 알겠는데 이미지도 가능할까요? 아쉽게도 이미지(gif, jpeg등)는 이미 압축을 한 상태이기 때문에 또 하면 안된다고 합니다.
보통 JSP/서블릿에서는 필터를 이용해서 gzip으로 압축을 하게 되죠. HeadFirst JSP/Sevet 에서도 필터에서 압축필터를 예제로 필터를 설명하고 있습니다.
여튼 gzip은 자바의 GZIPOutputStream을 이용해서 아래처럼 하실 수 있습니다.
.. 중략..
response.addHeader("Content-Encoding", "gzip");
gzipstream = new GZIPOutputStream(output);
.. 중략..
5. 스타일시트는 위에 넣어라
=> 왜 그럴까여? 그건 css가 다 다운받지 않으면 html의 랜더링이 안되고 그럼 빈화면이 계속 유지되기 때문입니다. 즉 css는 무조건 빨리 받아야 하는것이죠
헌데 이 css를 선언하는데에도 방법이 두가지가 있습니다. @import와 link태그가 그 주인공인데요 @import요소는 그 밖의 요소보다 앞서서 선언되어야 하고 또한 성능면에서도 link태그보다 떨어지므로 link 태그를 써야한다고 하는군요! 참고로 브라우져가 css를 젤 먼저 읽는 이유는 아래와 같다고 합니다
스타일시트가 아직 로딩 중인데도 렌더링 트리를 구성하는 것은 상당히 비효율적이다. 스타일시트가 로드 완료되고 분석될 때까지 화면에 그리는 작업을 피하는 것이 좋기 때문이다. 그렇지 않으면 화면에 표시될 콘텐츠의 스타일 정보가 완전하지 않은데도 화면에 나타나는 FOUC(flash of unstyled content의 약어로 스타일이 적용되지 않은 콘텐츠가 나타나는 것) 현상이 나타난다. - 데이비트 하이엇(Daive Hyatt) - |
1) CSS를 아래에 위치시킨 페이지 : http://stevesouders.com/hpws/css-bottom.php
2) CSS를 상위에 시킨 페이지 : http://stevesouders.com/hpws/css-top.php
3) @import를 이용해서 선언한것 : http://stevesouders.com/hpws/css-top-import.php
4) 스타일이 뒤늦게 적용되는 것 : http://stevesouders.com/hpws/css-fouc.php
6. 스크립트는 아래에 넣어라
=> 스크립트를 페이지 아래로 이동시킨다는 것은 더 많은 콘텐츠가 점진적인 랜더링을 할 수 있게 만든다는 것을 의미합니다
1) 스크립트를 위에 넣었을 경우 : http://stevesouders.com/hpws/js-top.php
2) 스크립트를 아래에 넣었을 경우 : http://stevesouders.com/hpws/js-bottom.php
3) 스크립트 위 vs 아래 : http://stevesouders.com/hpws/move-scripts.php
보통 css와 함께 위에 넣고 쓰지죠? 밑에 넣는것이 더 좋다고 하니 한번 생각해보심이.. ^^
7. CSS Expression을 피하라
=> CSS Expression은 CSS 속성을 동적으로 설정하는 기능이다. 문제는 expression 메소드는 IE에서만 되고 다른 브라우져에서는 무시된다. 웹 표준화니 아예 안쓰는것이 상책입니다 -_-
8. 자바스크립트와 CSS를 외부 파일에 넣어라
=> 규칙 1에서도 얘기했지만 그냥 한번만 다운받는다고 치면 인라인이 더 빠릅니다 헌데 왜 외부로 넣어야 할까요? 그건 캐시가 되기 때문입니다다. 즉 자주 들어가는 페이지는 캐시가 되어야 함으로 외부로 빼는것이 합당하다는것이죠. 그리고 여기서 저자의 멋진 아이디어가 나옵니다 그것은 무엇이냐면 이 둘만의 장점을 모아서~ 인라인으로 뿌리되 만약 캐시에 없다면 element를 인위적으로 생성하는 것이죠 ^^
예제를 보면 바로 이해갈듯 합니다
<script type="text/javascript">
function doOnload() {
setTimeout ( "downloadComponents()", 1000)
}
window.onload = doOnload;
// 자바스크립트를 이용하여 외부 구성요소를 동적으로 다운로드
function downloadComponents() {
downloadJS("http://stevesouders.com/hpws/testsma.js");
downloadJS("http://stevesouders.com/hpws/testsm.css");
}
}
// 스크립트를 동적으로 다운로드
function downloadJS(url) {
var elem = document.createElement("script");
elem.src = url;
document.body.appendChild(elem);
}
// 스타일시트를 동적으로 다운로드
fuction downloadCSS(url) {
var elem = document.createElement("link");
elem.rel = "stylesheet";
elem.type = "text/css";
elem.href = url;
document.body.appendChild(elem);
}
</script>
멋지죠?
헌데 보통 외부로 빼는것은 캐시를 쓰기 때문이기도 하지만 유지보수를 위해서라도 따로 빼야합니다. 하나의 jsp에 스크립트와 css가 다 들어가 있으면 토 나오기 쉽상이죠 -_-ㅋ
9. DNS 조회를 줄여라
=> 사실 이것은 좀 오버하는 경향이 있는듯 합니다 'ㅜ'; DNS 조회를 줄이기 위해 도메인을 줄이고 서버 아이피를 셋팅하라이겁니다 참고로 IP 주소를 조회하는데 20 ~ 120 ms정도가 소비되니 이것을 줄이기 위해서니깐 제 생각엔 가장 마지막에 해야할 작업이 아닐지 -_-
참고로 이 챕터를 보면서 DNS 캐싱도 있다는 것을 알게 됩니다. 이것은 우리가 쓰는 코넷이나 KT넷의 DNS 서버에서 해당 ip에 대한 캐싱을 해주는 것으로 이것은 우리가 핑할때 나오는 TTL(Time-lo-live) 값과 연관이 있고 이것은 또한 클라이언트에게 얼마나 오래 캐시에 저장할지를 말해줍니다.
ipconfig /displaydns 하면
dna.naver.com
----------------------------------------
데이터 이름 . . . . . : dna.naver.com
데이터 유형 . . . . . : 1
TTL(Time To Live) . : 282
데이터 길이 . . . . . : 4
섹션 . . . . . . . : 응답
(호스트) 레코드 . . . : 202.131.28.60
kmlocal.alpensiaresort.co.kr
----------------------------------------
데이터 이름 . . . . . : kmlocal.alpensiaresort.co.kr
데이터 유형 . . . . . : 1
TTL(Time To Live) . : 86400
데이터 길이 . . . . . : 4
섹션 . . . . . . . : 응답
(호스트) 레코드 . . . : 127.0.0.1
이렇게 나옴을 알수 있습니다. 참고로 디폴트가 1일이라서 그런지 로컬에서 지정한것은 60*60*24 값임을 알수 있습니다. 네이버는 5분이 채 안되는군요. 참고로 이렇게 지정되어 있는것은 DNS 서버가 설정한 값을 우리 로컬에서 보여준것이고 이런 DNS 캐싱을 브라우져에서도 할수 있습니다
여기서 중요한 것은 keep-Alive 입니다 keep-alive가 1분이면 TCP 연결은 아무런 통신 내용이 없어도 1분까지는 유효하다는 뜻입니다. 즉 이 1분동안은 DNS 조회가 필요하지 않다는 뜻이죠 그러니 불필요한 DNS 조회를 줄일려면 Kepp_Alive를 사용하고 도메인 수를 줄여 DNS 조회수를 줄여야 합니다.
10. 자바스크립트 최소화하라
=> 이것은 규칙 1에서 확장한 내용입니다. 요청을 줄일려면 요청도 적게 해야하고 파일의 사이즈도 줄여야 하니 말이죠. 자바스크립트를 줄이는것에는 크게 두가지 방법이 있습니다
최소화 - 코드의 불필요한 문자를 줄여서 파일 크기를 줄여 로딩 시간을 개선하는 것을 말합니다.
난독화(objfuscation) - 최소화처럼 주석과 공백을 줄여주지만 난독화는 코드 또한 변경하여 알아보기 힘들게 만듭니다
난독화가 더 사이즈를 줄여주긴 하지만 복잡하기 때문에 에러가 발생할 확률이 높고 또한 gzip을 이용하면 최소화나 난독화를 한것이나 같은 비율로 압축이 되기 때문에 저자는 난독화보다는 최소화를 권장하고 있습니다
요즘 jQuery나 Ext-js등 오픈라이브러리등도 다 이름.min.js 처럼 해서 최소화된 javascript를 제공하니 실제 운영시에는 min.js를 이용하면 될것 같습니다.
일반 스크립트.
jQuery.fn.checkbox = function(options) {
/* IE < 7.0 background flicker fix */
if ( jQuery.browser.msie && (parseFloat(jQuery.browser.version) < 7) )
{
document.execCommand('BackgroundImageCache', false, true);
}
/* Default settings */
var settings = {
cls: 'jquery-checkbox', /* checkbox */
empty: 'empty.png' /* checkbox */
};
최소화된 스크립트
jQuery.fn.checkbox=function(c){if(jQuery.browser.msie&&(parseFloat(jQuery.browser.version)<7)){document.execCommand('BackgroundImageCache',false,true)}
최소화 - 더글라스 크록퍼드(Douglas Crockford)
http://crockford.com/javascript/jsmin.html
1) 일반적인 큰 스크립트 - http://stevesouders.com/hpws/js-large-normal.php
2) 최소화한 큰 스크립트 - http://stevesouders.com/hpws/js-large-minify.php
3) 난독화한 큰 스크립트 - http://stevesouders.com/hpws/js-large-obfuscate.php
11. 리다이렉트를 피하라
=> 리다이렉트(redirect)는 사용자를 한 URL에서 다른 URL로 다시 보내는 것을 말합니다. 헌데 이 리다이렉트는 HTML 문서 자체의 다운로드를 지연시키기 때문에 가장 안좋다고 하는군요 저자가 가장 많이 일어나는 것은 주소 뒤에 슬래시(/)빼는 것이라고 합니다. 기존의 주소가 달라서 서버가 알아서 옮겨주는데 정확한 주소가 아니기때문에 301응답과 함께 서버가 /를 붙여서 해당 url로 리다이렉트된다고 합니다. 음 뭐 그렇다고 안 쓸수는 없으니 최소한으로 써야겠습니다
12. 중복되는 스크립트를 제거하라
=> 이건 뭐 당연히 중복시키면 안되겠죠 가뜩이나 지금 있는것도 줄이는 판국에 ㅎㅎ. 실수로 외부에서 가져오고 있는데 인라인으로 호출하고 있을지도 모르니 항상 체크해보아야 하겠습니다.
13. ETag를 설정하라
=> ETag(Entity Tag)는 웹 서버와 브라우져가 캐시된 구성요소의 유효성을 확인하기 위해서 사용하는 매커니즘입니다. 브라우저의 캐시에 저장되어 있는 구성요소와 원본 서버의 구성요소가 일치하는 판단하는 또 다른 방법이죠 HTML/1.1에 새롭게 추가되었는데요 ETag는 구성요소의 특정 버전을 나타내는 고유한 문자열로 이루어집니다.
이런 복잡한것은 안쓰는것이 상책이죠! -_-
14. 캐시를 지원하는 Ajax 만들기
=> 속도를 빠르게 하는데 Ajax라고 빠질 수 있을까요? ㅎㅎ
저자는 Ajax 응답에 캐시를 적용하는데에는 퀴리 스트링의 파라미터를 이용하는 것이 최선의 방법이라고 말합니다. 만약 캐시를 쓰지 않는다고 하면 기존의 규칙중에서 응답을 압축하거나 DNS 조회를 최소화하거나 스크립트를 최소화하거나 하는 기존의 규칙을 잘 지켜달라고 말하고 있습니다.
웹 개발자라면 한번쯤 읽어 볼만한 책인것 같습니다. ^^
책 분량이 얼마 안되서 부담도 되지 않고 또한 책의 마지막에 미국 상위 10개 사이트에 대해서 속도 개선에 대해 분석을 는것도 좋네요
유용한 URL
저자가 만든것 같은데요 기존 책에 잇는 내용보다 살이 더 많이 붙어있네요.^^
http://developer.yahoo.com/performance/rules.html
유용한 툴
1. IE watch라고 Http요청을 보여주는 것이 있습니다. 쉐어웨어버전이니 알아서 잘~ 쓰세용
=> http://file.naver.com/pc/view.html?fnum=220668&cat=60
2. Http 패킷 분석 툴. HTML문서와 관련된 HTTP 요청을 보여주고 HTTP 차트는 구성요소 다운로드에서 생기는 병목지점을 쉽게 확인
=> http://alphaworks.ibm.com/tech/pagedetailer
3. 유용한툴을 모아둔 포스팅이 있네요 ^^
=> http://xmlangel.blogspot.com/2009/02/blog-post.html
[출처] http://bluejames77.blog.me/80085811244
[출처] [인터넷/웹] 웹 사이트 최적화 기법|작성자 주한길
'Internet W3' 카테고리의 다른 글
[REST ②] Java Restlet을 이용한 RESTful 웹서비스의 구현 (0) | 2015.07.21 |
---|---|
[REST ①] RESTful 웹서비스에 대해 알아보자! (0) | 2015.07.21 |
웹사이트 성능 최적화 정리 (High Performance Web Sites) (0) | 2015.07.17 |
CERN, NCSA, W3C 개요 (0) | 2015.07.17 |
RPC, CORBA, DCOM, SOAP, REST 의 개요 (0) | 2015.07.17 |