본문 바로가기
Development

웹사이트 최적화

by Dev. Jkun 2013. 5. 29.
반응형

출처 : http://blog.naver.com/lipaz/100117319356


01. Ajax 성능 제대로 이해하기

이미 빠른 부분을 더 빠르게 하는 것보다 많이 느린 부분을 조금더 빠르게 하는것이 효과적이다.
일반적인 성능 저하의 원인은 자바스크립트보다는 DOM이다.

02. 빠른 웹 응용프로그램 만들기

브라우저는 하나의 스레드로 이벤트를 처리한다. => 하나의 이벤트가 실행되는 동안 다른 이벤트는 처리할 수 없다.

'충분히 빠르다?' - Jakob Nielsen

  • 0.1초 : 사용자가 UI에서 보여주는 개체를 직접 조작한다고 느낄 수 있는 최대시간
  • 1초 : 사용자가 컴퓨터가 작업을 끝낼 때까지 과도하게 기다릴 필요 없이 자연스럽게 명령을 내린다는 느낌을 가질 수 있는 최대 시간.
  • 10초 : 사용자가 현재 작업에 열중할 수 있는 최대 시간
    (10초 이상인 경우 작업의 진행 상황을 표시해야 한다.)
    • 페이지가 0.1초 이상 걸리면 매끄럽지 못한 느낌이 나지 않고, 1초 이상 걸리면 느리다는 느낌이 들며, 10초 이상이 걸리면 사용자는 떠난다.

Profiler : Firebug의 경우 Firefox 프로세스 내에서 실행되기 때문에 데이터의 왜곡이 많이 발생 할 수 있다.

브라우저의 지연시간으로 인한 표시 http://www.nczonline.net/blog/2009/01/05/what-determines-that-a-Script-is-long-running/

메모리 사용이 응답 시간에 미치는 영향
  • GC(garbage collection)이 메모리 해제를 할때 런타임이 일순간 멈춘다.
  • 응용프로그램의 메모리 사용량이 늘어나면 더 이상 사용되지 않는 객체를 찾아 힙 전체를 뒤지는데 필요한 시간이 늘면서 결국 사용자가 체감할 수 있는 수준까지 느려진다.
    메모리 문제 해결
  • 메모리 양 관찰 http://blog.pavlov.net/2008/03/11/firefox-3-memory-usage/의 Measuring Memory Use 참고
  • 메모리에서 더이상 사용되지 않는 객체는 delete로 해제
  • 웹페이지 DOM에서 필요하지 않는 노드 제거
    var page = { address : "http://naver.com/" };
    page.contents = getContents(page.address);
    ...
    //더이상 contents가 필요 없으면
    delete page.contents;
    ...
    var noteToDelete = document.getElementById("test");
    //DOM에서 사용하지 않는 노드 제거 + 메모리 해제
    delete nodeToDelete.parent.removeChild(nodeToDelete);

03. 초반 다운로드 분산

대부분의 사이트에서 다운로드하는 함수 중 onload 이벤트가 발생할 때까지 호출되지 않는 함수의 비율은 평균 70%나 된다!

어디를 쪼개면 될까?

04. 블로킹 없이 스크립트 로드하기

SCRIPT 태그는 실행될때 blocking을 하기 때문에 성능에 안좋은 영향을 미친다.
브라우저가 외부 스크립트를 다운로드하기 시작하면 해당 스크립트가 완전히 다운로드되어 파싱하고 실행될때까지 다른일은 하지 않는다. (IE8은 다른 스크립트를 동시 다운로드하나 다른 일(css처리 등)은 병렬처리 안한다.)
중간에 SCRIPT태그가 실행이 오래 걸릴경우 화면이 더디게 나타나 보인다.

스크립트를 사이좋게 만드는 방법
  • XHR Eval
    • javsscript source를 XHR로 다운 받아 eval 시킨다.
  • XHR Injection
    • javascript source를 XHR로 다운 받아 스크립트 태그로 생성후 head 태그에 넣는다.
  • Iframe 사용
    • iframe으로 js를 로드한다.
    • iframe내의 스크립트를 사용하기 위해서는 서로 참조 할 수 있도록 수정해야 한다.
      //부모(main)
      document.getEkementById('iframe1').contentWindow.FunctionName
      //자식(iframe)
      parent.document.body. ...
    • iframe은 다른 DOM에 비해 10이상의 많은 비용이 든다.
  • script DOM Element
    • DOM Element생성 후 src속성을 동적으로 지정
    • 다른 구성요소를 동시에 다운로드 하는 것이 가능
      var scriptElem = document.createElement('script');
      scriptElem.src = "http://domain.com/A.js";
      document.getElementByTagName('head')[0].appendChild(scriptElem);
  • document.write script tag
    • document.write를 이용하여 페이지에 script html 태그 삽입
      document.write("<script type="text/javascript" src="A.js"></script>");
    • IE만 다른 구성요소의 동시 다운로드 가능
    • document.write는 다른 상태를 block한다. - 스크립트가 다운되는 동안 다른 리소스는 block된다.
  • 고급 스크립트 다운로드 기법 요약
    기법동시 다운로드다른 도메인 가능기존스크립트 사용작업중 표시순서보장추가코드(byte)
    Normal Script SrcIE8, Saf4YYIE, Saf4, FF, ChrIE, Saf4, (FF, Chr, Op)~50
    XHR EvalIE, FF, Saf, Chr, OpNNSaf, Chr-~500
    XHR InjectionIE, FF, Saf, Chr, OpNYSaf, Chr-~500
    iframeIE, FF, Saf, Chr, OpNNIE,FF,Saf, Chr-~50
    DOM ElementIE, FF, Saf, Chr, OpYYFF, Saf, ChrFF, Op~200
    DeferIE, Saf4, Chr2, FF3.1YYIE, FF, Saf, Chr, OpIE, FF, Saf, Chr, Op~50
    document.writeIE, Saf4, Chr2, OpYYIE, FF, Saf, Chr, OpIE, FF, Saf, Chr, Op~100

*스크립트 로딩 기법 선택을 위한 결정 트리

05.비동기 스크립트와 결합시키기

  • 비동기 방식으로 순서 보존하기
    : 결론 - 존레식의 블로그 "Degrading Script Tag" http://ejohn.org/blog/degrading-script-tags/
    <script type=""></script>"text/javascript">
    var aExamples = [['a.php', 'b.php'], ... ];

    function init() {
    EFWS.Menu.createMenu('exampleBtn', aExample);
    }

    var domscript = document.createElement('script');
    domscript.src = "menu.js"
    domscript.text = "init();" // Opera는 innerHTML

    document.getElementsByTagName('head')[0].appendChild(domscript);

06.인라인 스크립트를 올바르게 배치하기

인라인 스크립트도 외부 스크립트와 동일한 이유(실행 순서보존, document.write로 인한 의존성)로 동시 다운로드와 렌더링을 방해한다.
이를 피해가기 위해

  • 인라인 스크립트를 맨 밑으로 옮겨라.
  • 자바스크립트 실행은 비동기 콜백을 통해 한다.
    • setTimeout 이용 (FF에서는 setTimeout time을 nglayoutinitial paint.delay값보다 크게 줘야 한다.)

css와 자바스크립트 순서 보존하기

스타일시트 다음에 인라인 스크립트가 오는 경우 스타일시트의 다운로드가 완료되기 전까지는 브라우저가 인라인 스크립트를 실행하지 않고 기다린다.
(스타일시트 바로 다음에 인라인 스크립트가 오면 그 후에 모든 리소스의 다운로드가 지연된다.)

해결방법은 인라인 스크립트를 스타일시트와 다른 리소스 사이에 넣지 않는것이다.
인라인 스크립트는 스타일시트 전 또는 다른 리소스 다음에 넣야 한다.
일반적인 권고 사항은 '인라인 스크립트는 스타일시트 위에 넣어라'

07.효율적인 자바스크립트 작성하기

지역변수 사용

현재 코드 범위 밖에 있는 변수의 값(전역변수 등)을 두번이상 사용하는 경우 지역변수에 저장하여 사용
(var키워드를 빼먹으면 전역변수가 된다.)

수정전
function createChildFor(elementId) {
var element = document.getElementById(elementId),
newElement = document.createElement("div");
element.appendChild(newElement);
}
수정후 - 지역변수 사용
function createChildFor(elementId) {
var doc = document,
var element = doc.getElementById(elementId),
newElement = doc.createElement("div");
element.appendChild(newElement);
}

유효 범위 체인이 증가하면 느리다.

catch절에 너무 많은 코드를 넣지 않도록 한다.

효율적인 데이터 접근

  1. 빈번하게 접근하는 값은 꼭 지역변수에 저장
  2. 점 연산자가 사용된 만큼 해당 값을 읽어오는데 시간이 걸리기 때문에 두번 이상 사용하는 객체의 속성이나 배열의 항목을 지역변수에 저장하라.
  3. HTMLCollection의 멤버를 반복해서 참조해야 하는 경우 이들을 먼저 배열에 복사해 둬라.
    1. HTMLCollection : var divs = document.getElementByTagName("div"); 에서 divs가 HTMLCollection이 된다. divs속성인 length에 여러번 접근할때는 지역변수에 저장하여 접근하라.

실행 경로 제어

  • if문 : 검사해야 하는 값이 2개 이하인 경우, 특정 범위를 쉽게 구분할 수 있는 숫자를 이용할 경우
  • switch : 2~10개의 항목을 검사하는 경우, 특정 범위가 없는 경우
  • 배열 검색 : 10개 이상의 값을 가질 경우, 검색 조건의 결과가 특정한 하나의 값일 경우

빠른 반복문

  1. length 값은 지역변수에 할당하여 사용하라.
  2. 지정한 변수의 길이를 증가하게 하는것이 아니라 감소하게 하라 (50% 실행시간을 절약할 수 있다.)
  3. 조건문에서 조건식 보다는 변수가 0이되면 종료되도록 하라
  4. 배열에서 indexOf를 피하라
  5. for-in 반복문을 피하라. (JSON 객체에서 속성 이름을 모를 경우만 사용)
  6. 아주 많은 양의 반복을 할 때 처리 http://home.earthlink.net/~kendrasg/info/js_opt/

문자열 최적화

  • +연산과 ,join메서드는 최근의 브라우저에서는 거의 차이가 없다.(도리어 +연산자가 더 빠르다.)
  • 그러나 IE6, IE7에서 많은 양(문자열이 20글자보다 작고 문자열의 수가 1000개 이상일 때)의 string을 처리할 때는 유효하다.

문자열 공백 제거

오랜시간 동작되는 스크립트는 피하라

"JavaScript that executes in whole seconds is probably doing something wrong. ..." - Brendan Eich

  • 너무 많은 DOM 작업
  • 너무 많은 일을 하는 반복문
  • 너무 많은 재귀함수의 사용

타이머를 이용하여 유연하게 만들기

타이머를 생성하여 실제로는 코드가 나중에 실행되도록 자바스크립트 엔진의 큐에 추가되도록 예약을 하라.

08. 코멧을 이용한 확장

커넥션을 열고 있어야 하므로 많은 사용자가 장시간 머물러 있는 서비스에서는 아직 적합하지 않다.
또, PHP, Erlang, Python, JAVA등의 언어를 사용해야 한다.

09. Gzip을 넘어서

최근의 브라우저는 Accept-Encoding 요청을 보내고 있으나 약 15%정도의 사용자들은 압축되지 않은 컨텐츠를 받게 된다.
이유는 15% 중 대부분이 웹프록시나 보안 소프트웨어 등에서 헤더를 변조하여 보내고 있기 때문이다.

압축을 하지 않는 사용자를 위한 사이즈 줄이기

a. 이벤트 델리게이션 이용

event delegation

자식 엘리먼트들을 가지고 있는 부모 엘리먼트에 이벤트를 하나만 추가하여
이벤트 버블링을 통해 자식 엘리먼트의 이벤트가 부모 엘리먼트에 전달되어 이벤트를 처리하는 기법

b. 상대 URL이용
현재 위치가 http:/www.example.com/path/page.html 일때

목적지상대 URL
http://subdomain.example.com//subdomain.example.com
http:/www.example.com/path/page2.htmlpage2.html
http:/www.example.com/index.html/index.html
http:/www.example.com/path2/page.html../path2/page.html
http:/www.example.com/path/page.html#f=bar#f=bar
http:/www.example.com/path/page.html?q=foo?q=foo

c. 여백 제거

d. inline style 피아기
e. javascript alias 사용

var $ = document.getElementById

10. 이미지 최적화

11. 도메인 공유

브라우저에 따른 서버당 커넥션의 수

브라우저HTTP/1.1HTTP/1.0
IE 6,724
IE 866
FF 228
FF 366
Safari 3,444
Chrome 1,266
Opera 9,1044

최적의 도메인 개수는 2개가 최적이다.
http://yuiblog.com/blog/2007/04/11/performance-research-part-4

example.com 과 www.example.com 은 다른것으로 인식한다!

12. 플러시를 통해서 문서 먼저 내리기

13. iframe의 자제

DOM 별 로드 하는데 소요되는 시간 (ms)

  1. of elements
101001000
IFRAME10981347
A0141
DIV0214
SCRIPT0440
STYLE0217

iframe은 onload 이벤트를 지연시킨다.
이를 회피하는 방법은 onload 이후 자바스크립트를 이용해서 동적으로 URL을 대입해 주는 것이다.

<iframe id=""></iframe>"iframe1" src="" >
<script type=""></script>"text/javscript">
window.onload = function() {
document.getElementById('iframe1').src = "http://iframe.example.com/";
}

13. CSS Selector


반응형

'Development' 카테고리의 다른 글

블록암호 (block cipher)  (0) 2013.05.29
CAPTCHA  (0) 2013.05.29
프로그래밍 배우는 법  (1) 2013.05.28
웹매트릭스 단축키 (Web Matrix Shot Cut Key)  (0) 2013.05.21
isDeveloper  (0) 2013.04.26

댓글