본문 바로가기
개발자의 정보/Web

Javascript 성능 향상을 위한 Tip

by pastory 2011. 5. 24.

갈수록 javascript(이하 js) 의 사용이 늘고 있다. 예 전의 간단한 js 가 더이상 아니게 되었고 오히려 javascript 가 html 보다 더 많은 내용을 차지하고 있는 것을 보는 것은 이제 흔한일이 되어 버린 것이다.

이렇듯 js 의 사용이 늘고 양이 점점 방대해져 가는 만큼 js 의 퍼포먼스(performance)도 더이상 남들만의 이야기는 아닐 것이다. 그래서 준비해 보았다.

목 적 : js 의 성능 향상을 위한 몇가지 테스트와 그 결과에 따른 tip 들을 정리 해 본다. 성능 테스트를 하기 위해 몇가지 툴을 사용할 수 있겠지만 좀더 직관적으로 빠르게 누구나 test 해보고 눈으로 확인할 수 있도록 간단한 퍼포먼스 객체를 만들었다.

   1:   
   2:  var PerformanceTool = function() {
   3:   var Timer = function() {
   4:   var sTime, eTime;
   5:   
   6:   this.start = function() {sTime = new Date();}
   7:   this.end = function() {eTime = new Date();}
   8:   this.time = function() {return (eTime - sTime);}
   9:   }
  10:   
  11:   this.test = function (fn)
  12:   {
  13:   var timer = new Timer();
  14:   timer.start();
  15:   fn();
  16:   timer.end();
  17:   return (timer.time());
  18:   }
  19:  }

이 객체를 가지고 테스트를 진행할 것이다.

목차

  • 1 객체 참조(Access object)
  • 2 IF 문과 SWITCH 문
  • 3 문자열(Concat String)
  • 4 HTML 추가하기
  • 5 결론
  • 6 그외의 알아둘 것들

객체 참조(Access object)

for 문장은 주로 배열에 관련하여 많은 사용을 하게 된다. 이때 js 에서중요한 관건은 배열 객체에 얼마나 자주 접근하느냐 하는 것이다. js 는 전체적으로 객체에 접근할때 마다 약간의 틈을 갖게 된다. 그래서 테스트 해 보았다.

1. for (var i = 0; i < a.length; i++){}
2. for (var i = a.length - 1; i >= 0; i--) {}

이 두가지 방식의 차이가 어떻게 나는지 확인해 보도록 하자.


   1:  function testFor(a)
   2:  {
   3:   writer("<hr />");
   4:   writer("<br />(var i = 0; i < a.length; i++) : ");
   5:   tool.test(function() {
   6:   for (var i = 0; i < a.length; i++){}
   7:   });
   8:   
   9:   writer("<br />(var i = a.length - 1; i >= 0; i--) : ");
  10:   tool.test(function() {
  11:   for (var i = a.length - 1; i >= 0; i--) {}
  12:   });
  13:  }

IF 문과 SWITCH 문

js를 포함한 모든 언어에 빼놓을 수 없는 문법이 바로 위에 언급한 if else 문장일 것이다.

1. if (a == b)
2. if (a < b)
3. if (a)
4. switch

위의 네가지를 테스트해 보았다.

   1: function ifswitch(count) 
   2: { 
   3:  var result = "<hr />ifelse(count) / count : " + count; 
   4:  
   5:  result += ("<br />if(a==b) : ") + tool.test(function(){ 
   6:  var a="a", b="b" 
   7:  for (var i = 0; i < count; i++) { if(a==b){}; } 
   8:  
   9:  }); 
  10:  
  11:  result += ("<br />if(a < b) : ") + tool.test(function(){ 
  12:  var a=1, b=2; 
  13:  for (var i = 0; i < count; i++) { if(a<b){}; } 
  14:  
  15:  }); 
  16:  
  17:  result += ("<br />if(a) : ") + tool.test(function(){ 
  18:  var a = true; 
  19:  for (var i = 0; i < count; i++) { if(a){}; } 
  20:  
  21:  }); 
  22:  
  23:  result += ("<br />switch a : ") + tool.test(function(){ 
  24:  var a = true; 
  25:  for (var i = 0; i < count; i++) { switch(a){ case true:}; } 
  26:  
  27:  }); 
  28:  
  29:  writer(result); 
  30: } 

문자열(Concat String)

가장 많이 하는 연산중에 string = string + other string; 과 같은 연산을 많이 할 것이다. 이 연산도 여러가지 방식이 있다.

1. string = string + other string
2. string += other string
3. StringBuffer ..

1, 2번은 대부분 아는 이야기 일 것이다. 그리고 3번은 배열을 이용하는 방법이다. 이 배열을 이용하는 방법을 잠깐 살펴보자. 참고를 위해 StringBuffer 라는 java클래스를 흉내내어 만들어 보았다.


   1: var StringBuffer = function() 
   2: { 
   3:  var buffer = []; 
   4:  
   5:  this.append = function(string) 
   6:  { 
   7:  buffer.push(string); 
   8:  return this; 
   9:  }; 
  10:  
  11:  this.toString = function() 
  12:  { 
  13:  return buffer.join(''); 
  14:  }; 
  15: } 

이렇게 만들어서 이녀석을 이용하는 것은 과연 어떨까?

테 스트하기 위한 간단한 기능을 구현해 보았다.


   1: function concatString(string, count) 
   2: { 
   3:  var result = "<hr />concatString(string) / string : " + string, 
   4:  a = "" 
   5:  ; 
   6:  
   7:  result += ("<br />a = a + string : "); 
   8:  result += tool.test(function() { 
   9:  for (var i = count; i >= 0; i--) { a = a + string; } 
  10:  }); 
  11:  result += " / a.length : " + a.length; 
  12:  
  13:  result += ("<br />a += s : "); 
  14:  result += tool.test(function() { 
  15:  a = ""; 
  16:  for (var i = count; i >= 0; i--) { a += string; } 
  17:  }); 
  18:  result += " / a.length : " + a.length; 
  19:  
  20:  result += ("<br />StringBuffer : "); 
  21:  result += tool.test(function() { 
  22:  var sb = new StringBuffer(); 
  23:  for (var i = count; i >= 0; i--) { sb.append(string); } 
  24:  a = sb.toString(); 
  25:  }); 
  26:  result += " / a.length : " + a.length; 
  27:  
  28:  writer(result); 
  29: } 

그렇다면 "a" 작은 데이터와 "abcdefghijklmnopqrstuvwxyz" 조금은 내용이 있는 데이터는 어떤 차이가 있을까?

HTML 추가하기

html 을 추가하거나 삭제하는 내용도 상당히 많이 쓰게 된다. 여기에도 한가지 방법만 있는 것은 아니다.

1. element.appendChild(document.createElement('DIV'))
2. element.innerHTML += '<table></table>'
3. 위에 언급한 StringBuffer + innerHTML
4. 추가로.. element.text

1 번은 dom 을 이용해 객체를 생성해 dom 엘리먼트에 붙이는 방법이고 2번은 직접 html을 수정하는 방법이다. 3번은 string 데이터를 모아서 한번에 innerHTML 을 통해 삽입하는 방법이다. 또한 여기에 추가로 element가 아닌 그냥 text 를 삽입하고 싶은 경우도 있을테니 4. element.text 까지 모두 3가지 경우를 테스트 해본다.

   1: function html(string, count) 
   2: { 
   3:  var result = "<hr />html(count) / count : " + count, tempElement = document.createElement("div");
   4:  
   5:  document.body.appendChild(tempElement); 
   6:  
   7:  result += ("<br />tempElement.appendChild(document.createTextNode): "); 
   8:  result += tool.test(function(){ 
   9:  for (var i = 0; i < count; i++) { 
  10:     tempElement.appendChild(document.createTextNode(string));
  11:  }
  12:  
  13:  }); 
  14:  
  15:  result += ("<br />tempElement.innerHTML : "); 
  16:  result += tool.test(function(){ 
  17:  for (var i = 0; i < count; i++) { tempElement.innerHTML += string; } 
  18:  }); 
  19:  
  20:  
  21:  result += ("<br />tempElement.innerHTML + StringBuffer : "); 
  22:  result += tool.test(function(){ 
  23:  var sb = new StringBuffer(); 
  24:  for (var i = 0; i < count; i++) { sb.append(string); } 
  25:  tempElement.innerHTML += string; 
  26:  }); 
  27:  
  28:  result += ("<br />tempElement.text : "); 
  29:  result += tool.test(function(){ 
  30:  for (var i = 0; i < count; i++) { tempElement.text += string; } 
  31:  }); 
  32:  
  33:  tempElement.innerHTML = ""; 
  34:  writer(result); 
  35: } 

결론

1. 객체의 접근이 빈번하게 일어날 경우 변수에 캐싱하여 사용한다.
2. 객체의 접근을 최소한으로 줄일 수 있는 방법을 찾아야 한다.
3. 같은 일을 할 수 있는 객체중 가장 빠르게 원하는 일을 할 수 있는 객체를 선택하여야 한다.

그외의 알아둘 것들

1. CSS 는 HEAD 에 Javascript 는 바닥에 첨부및 삽입하라.
2. script 파일은 별개의 파일로 작성하도록 한다. 이는 브라우저의 캐시를 이용하여 같은 스크립트를 브라우저 캐시에서 직접 가져와 사용하게 된다.
3. script 를 압축하고 주석을 제거하도록 한다.
4. integer = integer + 1 방식의 코드보다는 integer++ 코드가 이득을 볼 수 있다.

댓글