Microsoft 개발 주기의 중요한 부분은 제품 성능을 조정하는 것입니다. 성능 튜닝 역시 개발자가 주의해야 할 핵심 영역 중 하나입니다. 수년간의 개발 끝에 업계에서는 Win32 프로그램의 성능을 최적화하는 방법에 대해 많은 것을 배웠습니다.
오늘날 개발자가 직면하는 문제 중 하나는 DTHML 및 HTML 페이지가 빠르게 실행되거나 느리게 실행되는 원인을 잘 이해하지 못한다는 것입니다. 물론 2MB 이미지를 사용하지 않는 등 몇 가지 간단한 해결 방법도 있습니다. 우리는 DHTML 페이지의 성능을 향상시키기 위해 몇 가지 다른 흥미로운 기술을 사용하여 귀하의 페이지 성능을 향상시키는 데 도움이 되기를 바랍니다.
여기서는 테이블을 생성하는 프로그램의 예를 사용합니다. document.createElement() 및 element.insertBefore() 메서드는 1000개의 행(Row)이 있는 테이블을 만드는 데 사용됩니다. 각 행에는 하나의 열(셀)이 있습니다. 셀에 포함된 내용을 "텍스트"라고 합니다. 이 코드는 얼마나 나쁠 수 있습니까? 이렇게 작은 프로그램에는 조정의 여지가 얼마나 됩니까? 소개를 참조하시기 바랍니다.
처음에는 변수를 명시적으로 정의하지 않거나 한 페이지에서 VBScript와 JavaScript를 동시에 사용하는 등의 낮은 수준의 문제를 피하려고 노력했습니다. 프로그램은 다음과 같습니다:
<html>
<본문>
<스크립트>
var tbl, tbody, tr, td, 텍스트, i, 최대;
최대 = 1000;
tbl = document.createElement("TABLE");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
text = document.createTextNode("텍스트");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
PII233/64MB 메모리/NT4.0/IE5.0 시스템에서 이 프로그램을 실행하십시오. 페이지가 이 컴퓨터에서 로드됩니다. 페이지 로드 시작부터 페이지가 완전히 조용해지기까지(모든 이벤트가 실행되고 화면 표시가 완료됨)까지의 시간은 2328밀리초이며, 이는 이 테스트의 기준이기도 합니다(저는 Test1이라고 부릅니다).
이 페이지에서는 "문서", "본문", "창" 등과 같은 전역 개체를 자주 참조하는 작업이 매우 시간이 많이 걸립니다. 이러한 유사한 전역 변수를 모두 참조하는 것은 하나의 지역 변수를 참조하는 것보다 훨씬 더 비쌉니다.
그래서 첫 번째 개선 시도를 했습니다. 로컬 변수 "theBody"에 document.body를 캐시(Cache)하고
다음 코드를 추가했습니다.
var theBody = document.body;
그런 다음 다음 줄을 수정합니다:
document.body.insertBefore(tbl, null);
다음으로 변경합니다:
theBody.insertBefore(tbl, null);
두 번째 샘플을 확인하세요.
이 수정은 전체 시간에 큰 영향을 미치지 않았으며 단지 3ms만 단축되었습니다. 그러나 루프에 document.body 개체도 있고 해당 참조가 수정되면 이점이 상당할 것으로 나타났습니다.
그 후, 문서 개체를 캐시했습니다. 테스트에서 문서 개체는 총 3002번 참조되었습니다. 수정된 코드는 다음과 같습니다.
<html>
<본문>
<스크립트>
var tbl, tbody, tr, td, 텍스트, i, 최대;
최대 = 1000;
var theDoc = 문서;
var theBody = theDoc.body;
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("텍스트");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
세 번째 샘플을 보세요.
이 실행 시간은 2100ms에 불과하여 약 10%의 시간이 절약됩니다. 문서 개체를 직접 참조하는 대신 지역 변수를 사용하면 매번 평균 0.4밀리초가 절약됩니다.
성능을 최적화하는 일반적인 방법은 스크립트를 즉시 실행할 필요가 없을 때 <SCRIPT> 태그에 "defer" 속성을 설정하는 것입니다. (직접 스크립트는 함수 블록에 포함되어 있지 않으므로 로딩 과정 중에 실행됩니다.) "defer" 속성을 설정하면 IE는 스크립트가 로드되고 실행될 때까지 기다릴 필요가 없습니다. 이렇게 하면 페이지가 더 빨리 로드됩니다. 일반적으로 이는 즉시 실행 스크립트가 함수 블록에 가장 잘 배치되고 문서 또는 본문 개체의 onload 핸들러에서 함수를 처리한다는 의미이기도 합니다. 이 속성은 버튼 클릭, 특정 영역으로 마우스 이동 등 사용자 작업에 따라 실행해야 하는 일부 스크립트가 있는 경우에 유용합니다. 그러나 페이지가 로드되는 동안이나 이후에 실행해야 하는 일부 스크립트가 있는 경우 defer 속성을 사용하는 이점은 크지 않습니다.
다음은 defer 속성을 사용하여 수정된 코드 버전입니다.
<html>
<body onload="init()">
<스크립트 연기>
함수 초기화() {
var tbl, tbody, tr, td, 텍스트, i, 최대;
최대 = 1000;
var theDoc = 문서;
var theBody = theDoc.body;
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("텍스트");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</script>
</body>
</html>
네 번째 샘플을 확인하세요.
이 테스트의 시간은 2043ms입니다. 이는 기준 테스트에 비해 12% 증가한 수치이며, 이전 테스트에 비해 2.5% 높은 수치입니다.
아래에서 이야기하는 개선 방법은 물론 매우 유용하지만 조금 더 번거롭습니다. 요소를 생성한 다음 이를 트리형 구조에 삽입해야 하는 경우 먼저 큰 하위 트리에 삽입한 다음 큰 하위 트리를 트렁크에 삽입하는 것보다 트렁크에 직접 삽입하는 것이 더 효율적입니다. 예를 들어, 각 행에 하나의 열이 있고 열에 일부 텍스트가 있는 테이블을 생성하는 경우 다음을 수행할 수 있습니다.
1. <TR> 생성
2. <TD> 생성
3. TextNode 노드 생성
4. TextNode를 <TD에 삽입 >
5. <TR>에 <TD> 삽입
6. TBODY에 <TR> 삽입
다음 방법보다 느린 경우:
1. <TR> 생성
2. <TD> 생성
3. TextNode 생성
4. <TR > 삽입 TBODY에 삽입
5. <TR>에 <TD> 삽입
6. <TD>에 TextNode 삽입
위의 네 가지 테스트는 모두 전자의 방법을 사용합니다. 다섯 번째 테스트에서는 후자의 방법을 사용했습니다. 코드는 다음과 같습니다.
<html>
<body onload="init()">
<스크립트 연기>
함수 초기화() {
var tbl, tbody, tr, td, 텍스트, i, 최대;
최대 = 1000;
var theDoc = 문서;
var theBody = theDoc.body;
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("텍스트");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore(text, null);
}
}
</script>
</body>
</html>
다섯 번째 샘플을 보세요.
Test5에는 1649ms만 걸립니다. 이는 지난 테스트에 비해 25% 개선되었으며 기준선보다 거의 30% 빠릅니다.
후속 수정은 미리 만들어진 스타일시트를 사용하여 이루어졌습니다. 미리 만들어진 스타일 시트를 사용하거나 <COL> 태그를 통해 설정된 테이블의 열 너비입니다. <COL> 태그가 없는 경우 각 열의 너비가 균등하게 분배됩니다. 각 열의 크기 등을 다시 계산할 필요가 없기 때문에 스타일 시트를 사용하면 특히 테이블의 열 수가 많은 경우 실제로 성능이 향상됩니다.
스타일 시트(CSS)를 추가하는 코드는 다음과 같이 매우 간단합니다.
tbl.style.tableLayout = "fixed";
여섯 번째 샘플을 확인하세요.
테스트의 테이블에는 열이 하나만 있었기 때문에 이 변경으로 인해 페이지 성능이 1.6%만 향상되었습니다. 열이 더 많으면 성능 향상이 더욱 커집니다.
마지막 두 테스트에서는 테이블에 텍스트가 삽입되는 방식이 변경되었습니다. 이전 테스트에서는 먼저 TextNode를 만든 다음 이를 TD에 삽입했습니다. 대신 Test7에서는 innerText를 통해 포함된 텍스트를 지정합니다. 수정된 코드는 다음과 같습니다:
td.innerText = "Text";
일곱 번째 샘플을 살펴보세요.
놀랍게도 이 수정으로 인한 차이는 엄청났습니다. 지난번에 비해 성능이 9% 향상되었고 원본에 비해 총 36% 성능이 향상되었습니다. 시간 범위는 처음 2323ms부터 마지막 1473ms까지입니다.
이제 거의 모든 사람들이 element.innerHTML을 사용하는 것이 매우 느리다는 것을 알고 있습니다. 얼마나 느린지 확인하기 위해 마지막 테스트를 수행했습니다. innerText 대신 innerHTML을 사용하여 텍스트를 삽입하는 것입니다. 이로 인해 성능이 크게 저하됩니다. 시간은 3375ms에 도달했는데, 이는 지난 테스트보다 80%, 기준 테스트보다 45% 느렸습니다. 분명히 innerHTML은 시간이 많이 소요됩니다.
HTML 페이지 성능 조정은 Win32 응용 프로그램 성능 조정과 유사합니다. 무엇이 느리고 무엇이 빠른지 알아야 합니다. 이러한 방법이 페이지 성능을 향상시키는 데 도움이 되기를 바랍니다.