AJAX의 출현으로 인해 웹 애플리케이션 클라이언트의 작동 모드가 크게 바뀌었습니다. 이를 통해 사용자는 귀찮은 페이지 새로 고침을 자주 겪지 않고도 작업에 집중할 수 있습니다. 이론적으로 AJAX 기술은 사용자 작업 대기 시간을 크게 줄이고 네트워크의 데이터 트래픽을 줄일 수 있습니다. 그러나 항상 그런 것은 아닙니다. 사용자들은 AJAX를 사용하는 시스템의 응답 속도가 느려진다고 불평하는 경우가 많습니다.
저자는 수년 동안 AJAX 연구 개발에 참여해 왔으며 중국에서 비교적 성숙한 AJAX 플랫폼인 dorado 개발에 참여했습니다. 저자의 경험에 따르면 이 결과의 근본 원인은 AJAX가 아닙니다. 시스템 응답 속도의 감소는 불합리한 인터페이스 디자인과 불충분한 프로그래밍 습관으로 인해 발생하는 경우가 많습니다. 아래에서는 AJAX 개발 프로세스 중에 주의해야 할 몇 가지 측면을 분석합니다.
클라이언트 프로그래밍 및 원격 프로시저 호출을 올바르게 사용합니다.
클라이언트 측 프로그래밍은 주로 JavaScript를 기반으로 합니다. JavaScript는 해석된 프로그래밍 언어이므로 운영 효율성은 Java보다 약간 낮습니다. 동시에 JavaScript는 브라우저와 같이 엄격하게 제한된 환경에서 실행됩니다. 따라서 개발자는 클라이언트 측에서 어떤 논리를 실행할 수 있는지 명확하게 이해해야 합니다.
실제 애플리케이션에서 클라이언트 측 프로그래밍을 어떻게 사용해야 하는지는 개발자의 경험과 판단에 따라 달라집니다. 여기서 많은 문제는 이해될 수밖에 없습니다. 제한된 공간으로 인해 여기에서는 다음과 같은 예방 조치를 대략적으로 요약합니다.
원격 프로시저 호출을 가능한 한 자주 사용하지 마십시오. 예를 들어 루프 본문에서는 원격 프로시저 호출을 사용하지 마십시오.
▶ 가능하다면 AJAX 원격 프로시저 호출(비동기 원격 프로시저 호출)을 사용하세요.
클라이언트 측에 무거운 데이터 작업을 배치하지 마십시오. 예를 들어 대규모 데이터 복사 작업 배치, 대량의 데이터 순회가 필요한 계산 등이 있습니다.
DOM 객체의 동작 방식을 개선합니다.
클라이언트 측 프로그래밍에서 DOM 개체에 대한 작업은 종종 CPU 시간을 가장 많이 차지합니다. DOM 개체 작업의 경우 다양한 프로그래밍 방법 간의 성능 차이가 매우 큰 경우가 많습니다.
다음은 정확히 동일한 결과를 갖는 세 가지 코드 조각입니다. 해당 기능은 웹 페이지에 10x1000 테이블을 만드는 것입니다. 그러나 달리는 속도는 크게 다릅니다.
/* 테스트 코드 1 - 소요 시간: 41초*/
var table = document.createElement("TABLE");
document.body.appendChild(테이블);
for(var i = 0; i < 1000; i++){
var 행 = table.insertRow(-1);
for(var j = 0; j < 10; j++){
var cell = objRow.insertCell(-1);
cell.innerText = "( " + i + " , " + j + " )";
}
}
/* 테스트 코드 2 - 소요 시간: 7.6초*/
var table = document.getElementById("TABLE");
document.body.appendChild(테이블);
var tbody = document.createElement("TBODY");
table.appendChild(tbody);
for(var i = 0; i < 1000; i++){
var row = document.createElement("TR");
tbody.appendChild(행);
for(var j = 0; j < 10; j++){
var cell = document.createElement("TD");
row.appendChild(셀);
cell.innerText = "( " + i + " , " + j + " )";
}
}
/* 테스트 코드 3 - 소요 시간: 1.26초*/
var tbody = document.createElement("TBODY");
for(var i = 0; i < 1000; i++){
var row = document.createElement("TR");
for(var j = 0; j < 10; j++){
var cell = document.createElement("TD");
cell.innerText = "( " + i + " , " + j + " )";
row.appendChild(셀);
}
tbody.appendChild(행);
}
var table = document.getElementById("TABLE");
table.appendChild(tbody);
document.body.appendChild(테이블);
여기서 "테스트 코드 1"과 "테스트 코드 2"의 차이점은 테이블 셀을 생성할 때 서로 다른 API 메서드가 사용된다는 점입니다. "테스트 코드 2"와 "테스트 코드 3"의 차이점은 처리 순서가 약간 다르다는 것입니다.
"Test Code 1"과 "Test Code 2" 사이에는 이렇게 큰 성능 차이를 분석할 수 없습니다. 현재 알려진 것은 insertRow와 insertCell은 DHTML의 테이블별 API이고 createElement와 AppendChild는 W3C DOM의 기본 API라는 것입니다. 전자는 후자를 캡슐화해야 합니다. 그러나 이것만으로는 DOM의 기본 API가 항상 객체별 API보다 낫다는 결론을 내릴 수는 없습니다. API를 자주 호출해야 하는 경우 성능에 대한 몇 가지 기본 테스트를 수행하는 것이 좋습니다.
"Test Code 2"와 "Test Code 3"의 성능 차이는 주로 빌드 순서의 차이에서 비롯됩니다. "테스트 코드 2"의 접근 방식은 먼저 가장 바깥쪽의 <TABLE> 객체를 생성한 다음 루프에서 <TR>과 <TD>를 순차적으로 생성하는 것입니다. "테스트 코드 3"의 접근 방식은 먼저 내부에서 외부로 전체 테이블을 메모리에 구축한 다음 웹 페이지에 추가하는 것입니다. 이는 브라우저가 페이지 레이아웃을 다시 계산하는 횟수를 최대한 줄이는 것입니다. 웹 페이지에 개체를 추가할 때마다 브라우저는 페이지의 컨트롤 레이아웃을 다시 계산하려고 시도합니다. 그러므로 메모리에 구성할 전체 개체를 먼저 생성한 다음 웹 페이지에 한 번에 추가할 수 있다면 가능합니다. 그러면 브라우저는 레이아웃 재계산만 수행합니다. 한 문장으로 요약하자면,appendChild를 나중에 실행할수록 좋습니다. 때로는 운영 효율성을 높이기 위해 RemoveChild를 사용하여 페이지에서 기존 컨트롤을 제거한 다음 구성이 완료된 후 페이지에 다시 배치하는 것을 고려할 수도 있습니다.
문자열 축적 속도를 향상시킵니다. AJAX를 사용하여 정보를 제출할 때 XmlHttp를 통해 POST 제출을 완료하기 위해 상대적으로 큰 문자열을 조합해야 하는 경우가 종종 있습니다. 이렇게 많은 양의 정보를 제출하는 것이 부적절해 보일 수도 있지만 때로는 그러한 요구에 직면해야 할 수도 있습니다. 그렇다면 JavaScript에서 문자열이 얼마나 빨리 축적됩니까? 먼저 다음 실험을 해보겠습니다. 길이가 30000인 문자열을 누적합니다.
/* 테스트 코드 1 - 소요 시간: 14.325초*/
var str = "";
for (var i = 0; i < 50000; i++) {
str += "xxxxxx";
}
이 코드는 14.325초가 걸렸으며 결과는 이상적이지 않았습니다. 이제 코드를 다음 형식으로 변경합니다.
/* 테스트 코드 2 - 소요 시간: 0.359초*/
var str = "";
for (var i = 0; i < 100; i++) {
var 하위 = "";
for (var j = 0; j < 500; j++) {
하위 += "xxxxxx";
}
str += 하위;
}
이 코드에는 0.359초가 걸립니다! 결과는 같습니다. 우리가 하는 일은 먼저 작은 끈 몇 개를 조립한 다음 더 큰 끈으로 조립하는 것뿐입니다. 이 접근 방식은 문자열 조립의 후반 단계에서 메모리에 복사되는 데이터 양을 효과적으로 줄일 수 있습니다. 이 원리를 알고 나면 테스트를 위해 위 코드를 더 분해할 수 있습니다. 아래 코드는 0.140초 밖에 걸리지 않습니다.
/* 테스트 코드 3 - 소요 시간: 0.140초*/
var str = "";
for (var i1 = 0; i1 < 5; i1++) {
var str1 = "";
for (var i2 = 0; i2 < 10; i2++) {
var str2 = "";
for (var i3 = 0; i3 < 10; i3++) {
var str3 = "";
for (var i4 = 0; i4 < 10; i4++) {
var str4 = "";
for (var i5 = 0; i5 < 10; i5++) {
str4 += "xxxxxx";
}
str3 += str4;
}
str2 += str3;
}
str1 += str2;
}
str += str1;
}
그러나 위의 접근 방식이 최선이 아닐 수도 있습니다! 제출해야 하는 정보가 XML 형식인 경우(사실 대부분의 경우 제출할 정보를 XML 형식으로 조합하려고 시도할 수 있음) DOM 객체를 사용하여 조합하는 보다 효율적이고 우아한 방법을 찾을 수도 있습니다. 우리 문자열의 문자. 다음 단락에서는 길이가 950015인 문자열을 조합하는 데 0.890초밖에 걸리지 않습니다.
/* DOM 객체를 사용하여 정보를 조합합니다. 소요 시간: 0.890초*/
var xmlDoc;
if (browserType == BROWSER_IE) {
xmlDoc = new ActiveXObject("Msxml.DOMDocument");
}
또 다른 {
xmlDoc = document.createElement("DOM");
}
var root = xmlDoc.createElement("루트");
for (var i = 0; i < 50000; i++) {
var node = xmlDoc.createElement("data");
if (browserType == BROWSER_IE) {
node.text = "xxxxxx";
}
또 다른 {
node.innerText = "xxxxxx";
}
root.appendChild(노드);
}
xmlDoc.appendChild(루트);
var str;
if (browserType == BROWSER_IE) {
str = xmlDoc.xml;
}
또 다른 {
str = xmlDoc.innerHTML;
}
려면 DOM 개체의 메모리 누수를 방지하세요.
IE에서 DOM 개체의 메모리 누수는 개발자가 종종 무시하는 문제입니다. 그러나 그것이 가져오는 결과는 매우 심각합니다! 이로 인해 IE의 메모리 사용량이 계속 증가하고 브라우저의 전체 실행 속도가 크게 느려집니다. 심각한 유출이 발생한 일부 웹 페이지의 경우 몇 번 새로 고쳐도 실행 속도가 두 배로 빨라집니다.
보다 일반적인 메모리 누수 모델에는 "순환 참조 모델", "클로저 함수 모델" 및 "DOM 삽입 순서 모델"이 포함됩니다. 처음 두 누수 모델의 경우 웹 페이지가 파괴될 때 역참조하여 이를 방지할 수 있습니다. "DOM 삽입 순서 모델"의 경우 일반적인 프로그래밍 습관을 변경하여 이를 피해야 합니다.
메모리 누수 모델에 대한 자세한 내용은 Google을 통해 빠르게 찾을 수 있으며, 이 기사에서는 너무 자세히 설명하지 않습니다. 하지만 여기서는 웹 페이지 메모리 누수를 찾아 분석하는 데 사용할 수 있는 작은 도구인 Drip을 추천합니다. 현재 최신 버전은 0.5이고 다운로드 주소는 http://outofhanwell.com/ieleak/index.php 입니다.
복잡한 페이지의 분할 로딩 및 초기화 IFrame을 사용하기가 매우 복잡하고 불편한 시스템의 일부 인터페이스에 대해 분할 로딩을 구현할 수 있습니다. 예를 들어 다중 페이지 탭 인터페이스의 경우 먼저 다중 페이지 탭의 기본 페이지를 다운로드하고 초기화한 다음 AJAH(비동기 JavaScript 및 HTML) 기술을 사용하여 다른 탭 페이지의 콘텐츠를 비동기적으로 로드할 수 있습니다. 이렇게 하면 인터페이스가 처음에 사용자에게 표시될 수 있습니다. 복잡한 인터페이스 전체의 로딩 과정을 사용자의 조작 과정으로 분산시킵니다.
‐ GZIP을 사용하여 네트워크 트래픽을 압축합니다.
위에서 언급한 코드 수준 개선 외에도 GZIP을 사용하여 네트워크 트래픽을 효과적으로 줄일 수도 있습니다. 현재 모든 일반 주류 브라우저는 이미 GZIP 알고리즘을 지원하고 있습니다. GZIP을 지원하려면 약간의 코드만 작성하면 되는 경우가 많습니다. 예를 들어, J2EE에서는 필터에서 다음 코드를 사용하여 클라이언트 브라우저가 GZIP 알고리즘을 지원하는지 확인한 다음 java.util.zip.GZIPOutputStream을 사용하여 필요에 따라 GZIP 출력을 구현할 수 있습니다.
/* 브라우저가 GZIP을 지원하는 방법을 결정하는 코드*/
개인 정적 문자열 getGZIPEncoding(HttpServletRequest 요청) {
String acceptEncoding = request.getHeader("Accept-Encoding");
(acceptEncoding == null) 경우 null을 반환합니다.
acceptEncoding = acceptEncoding.toLowerCase();
if (acceptEncoding.indexOf("x-gzip") >= 0) return "x-gzip";
if (acceptEncoding.indexOf("gzip") >= 0) return "gzip";
null을 반환;
}
일반적으로 HTML과 JSP에 대한 GZIP의 압축률은 약 80%에 달하며 서버와 클라이언트에서 발생하는 성능 손실은 거의 무시할 수 있습니다. 다른 요인과 결합하여 GZIP을 지원하는 웹사이트는 네트워크 트래픽의 50%를 절약할 수 있습니다. 따라서 GZIP을 사용하면 네트워크 환경이 특별히 좋지 않은 응용 프로그램의 성능을 크게 향상시킬 수 있습니다. HTTP 모니터링 도구인 Fiddler를 사용하면 GZIP 사용 전후에 웹페이지의 통신 데이터 양을 쉽게 감지할 수 있습니다. Fiddler의 다운로드 주소는 http://www.fiddlertool.com /fiddler/입니다.
웹 애플리케이션의 성능 최적화는 실제로 매우 큰 주제입니다. 제한된 공간으로 인해 이 기사에서는 일부 세부 사항만 다룰 수 있으며 이러한 세부 사항의 최적화 방법을 완전히 보여줄 수도 없습니다. 이 기사가 웹 애플리케이션, 특히 클라이언트 측 성능 최적화에 대한 모든 사람의 관심을 끌 수 있기를 바랍니다. 결국 서버 측 프로그래밍 기술은 수년 동안 모든 사람에게 알려져 왔으며 서버 측에서 성능을 활용할 가능성은 많지 않습니다. 클라이언트 측의 메소드 개선으로 놀라운 성능 향상을 가져올 수 있는 경우가 많습니다.