Node.js를 사용할 때 따르는 10가지 성능 규칙은 다음과 같습니다.
1. 동기 코드 사용을 피하세요
설계상 Node.js는 단일 스레드입니다. 단일 스레드가 많은 동시 요청을 처리할 수 있도록 하려면 스레드가 차단, 동기 또는 장기 실행 작업을 기다리도록 할 수 없습니다. Node.js의 독특한 특징은 비동기 구현을 달성하기 위해 위에서 아래로 설계되고 구현된다는 것입니다. 이는 이벤트 기반 프로그램에 이상적입니다.
안타깝게도 동기/차단 호출이 여전히 발생할 수 있습니다. 예를 들어 writeFile 및 writeFileSync와 같은 많은 파일 시스템 작업에는 동기 버전과 비동기 버전이 모두 있습니다. 코드를 사용하여 동기화 방법을 제어하더라도 호출을 차단하는 외부 함수 라이브러리를 실수로 사용할 수 있습니다. 이렇게 하면 성능에 미치는 영향이 엄청납니다.
// Good: write files asynchronously fs.writeFile('message.txt', 'Hello Node', function (err) { console.log("It's saved and the server remains responsive!"); }); // BAD: write files synchronously fs.writeFileSync('message.txt', 'Hello Node'); console.log("It's saved, but you just blocked ALL requests!");
초기화 로그 구현에 내용을 디스크에 쓰기 위한 동기 호출이 실수로 포함되었습니다. 성능 테스트를 수행하지 않으면 이 문제를 무시하기 쉽습니다. 개발자 상자에서 node.js 인스턴스에 대해 테스트할 때 이 동기 호출로 인해 초당 수천 개의 요청에서 수십 개의 요청으로 성능이 저하됩니다.
2. 소켓 풀을 닫습니다
Node.js http 클라이언트는 자동으로 소켓 풀링을 사용합니다. 기본적으로 각 호스트는 5개의 소켓으로 제한됩니다. 소켓을 재사용하면 리소스 증가를 제어할 수 있지만 동일한 호스트에서 들어오는 데이터에 대한 많은 동시 요청을 처리해야 하는 경우 일련의 병목 현상이 발생할 수 있습니다. 이 경우 maxSockets 값을 높이거나 소켓 풀을 끄는 것이 좋습니다.
// Disable socket pooling var http = require('http'); var options = {.....}; options.agent = false; var req = http.request(options)
3. 정적 리소스에 Node.js를 사용하지 마세요
CSS, 이미지 등 정적 리소스의 경우 Node.js 대신 표준 WebServer를 사용하세요. 예를 들어 LinkedIn Mobile은 nginx를 사용합니다. 또한 정적 자산을 전 세계 서버에 복사할 수 있는 CDN(콘텐츠 전달 네트워크)도 활용합니다. 여기에는 두 가지 이점이 있습니다. (1) node.js 서버의 로드를 줄일 수 있습니다. (2) CDN은 정적 콘텐츠를 사용자에게 더 가까운 서버에 전달할 수 있도록 하여 대기 시간을 줄일 수 있습니다.
4. 클라이언트에서 렌더링
서버 렌더링과 클라이언트 렌더링의 차이점을 빠르게 비교해 보겠습니다. node.js를 사용하여 서버 측에서 렌더링하는 경우 모든 요청에 대해 다음과 같은 HTML 페이지를 다시 보냅니다.
<!-- An example of a simple webpage rendered entirely server side --> <!DOCTYPE html> <html> <head> <title>LinkedIn Mobile</title> </head> <body> <div class="header"> <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/> </div> <div class="body"> Hello John! </div> </body> </html>
사용자 이름을 제외한 이 페이지의 모든 콘텐츠는 정적 콘텐츠입니다. 콘텐츠는 각 사용자 및 페이지 새로고침에 대해 동일합니다. 따라서 Node.js가 페이지에 필요한 동적 콘텐츠만 JSON 형식으로 반환하도록 하는 것이 더 효율적입니다.
{"이름": "존"}
페이지의 나머지 부분(모두 정적 HTML 마크업)은 JavaScript 템플릿(예: underscore.js 템플릿)에 배치할 수 있습니다.
<!-- An example of a JavaScript template that can be rendered client side --> <!DOCTYPE html> <html> <head> <title>LinkedIn Mobile</title> </head> <body> <div class="header"> <img src="http://mobile-cdn.linkedin.com/images/linkedin.png" alt="LinkedIn"/> </div> <div class="body"> Hello <%= name %>! </div> </body> </html>
성능 향상은 다음에서 비롯됩니다. 세 번째 지점에서 언급했듯이 정적 JavaScript 템플릿은 웹 서버(예: nginx)를 통해 서버 측에서 제공되거나 더 나은 CDN을 사용하여 구현할 수 있습니다. 또한 JavaScript 템플릿은 브라우저에 캐시되거나 로컬에 저장될 수 있으며 모든 초기 페이지가 로드된 후 클라이언트에 전송해야 하는 유일한 데이터는 JSON이며 이것이 가장 효과적입니다. 이 방법을 사용하면 CPU, IO 및 Node.js 로드를 크게 줄일 수 있습니다.
5. gzip을 사용하세요
많은 서버와 클라이언트가 요청과 응답을 압축하기 위해 gzip을 지원합니다. 클라이언트에 응답하든 원격 서버에 요청을 보내든 이 기능을 최대한 활용하세요.
6. 병렬화
원격 서비스 요청, DB 호출, 파일 시스템 액세스 등 모든 차단 작업을 병렬화해 보세요. 이렇게 하면 모든 차단 작업의 대기 시간이 아니라 가장 느린 차단 작업의 대기 시간이 줄어듭니다. 콜백과 오류 처리를 깨끗하게 유지하기 위해 Step을 사용하여 흐름을 제어합니다.
7.세션 자유화
LinkedIn Mobile은 Express 프레임워크를 사용하여 요청/응답 주기를 관리합니다. 많은 Express 예제에는 다음 구성이 포함됩니다.
app.use(express.session({ secret: "keyboard cat" }));
기본적으로 세션 데이터는 메모리에 저장되므로 특히 사용자 수가 증가함에 따라 서버에 막대한 오버헤드가 추가됩니다. MongoDB 또는 Redis와 같은 외부 세션 저장소를 사용할 수 있지만 각 요청은 세션 데이터를 검색하기 위한 원격 호출의 오버헤드를 발생시킵니다. 가능한 경우 가장 좋은 옵션은 모든 상태 비저장 데이터를 서버 측에 저장하는 것입니다. 위의 빠른 구성을 포함하지 않고 세션을 확보하면 더 나은 성능을 볼 수 있습니다.
8. 바이너리 모듈 사용
가능하다면 JavaScript 모듈을 바이너리 모듈로 교체하세요. 예를 들어 JavaScript로 작성된 SHA 모듈에서 Node.js용 컴파일 버전으로 전환하면 성능이 크게 향상됩니다.
// Use built in or binary modules var crypto = require('crypto'); var hash = crypto.createHmac("sha1",key).update(signatureBase).digest("base64");
9. 클라이언트 라이브러리를 표준 V8 JavaScript로 교체
JavaScript 환경이 다르기 때문에 많은 JavaScript 라이브러리가 웹 브라우저에서 사용하기 위해 생성됩니다. 예를 들어 일부 브라우저는 forEach, map 및 Reduce와 같은 기능을 지원하지만 일부 브라우저는 지원하지 않습니다. 따라서 클라이언트 라이브러리는 브라우저 차이를 극복하기 위해 비효율적인 코드를 많이 사용하는 경우가 많습니다. 반면 Node.js에서는 어떤 JavaScript 메소드가 유효한지 정확히 알 수 있습니다. V8 JavaScript 엔진은 ECMA-262 5판에 지정된 대로 Node.js의 ECMAScript 구현을 지원합니다. 클라이언트 라이브러리를 표준 V8 JavaScript 함수로 바꾸기만 하면 성능이 크게 향상됩니다.
10. 코드를 작고 가볍게 유지하세요
모바일 장치를 사용하면 액세스 속도가 느려지고 대기 시간이 길어질 수 있으므로 코드를 작고 가볍게 유지해야 합니다. 서버 코드에도 동일한 철학을 유지하세요. 때때로 자신의 결정을 되돌아보고 "이 모듈이 정말로 필요한가?", "우리가 이 프레임워크를 사용하는 이유는 무엇이며 오버헤드가 그만한 가치가 있는가?", "더 쉬운 방법을 사용할 수 있을까?"와 같은 질문을 스스로에게 물어보세요. " 일반적으로 코드가 작고 가벼울수록 더 효율적이고 빠릅니다.
해 보세요
우리는 모바일 앱을 빠르게 만들기 위해 열심히 노력하고 있습니다. iPhone 앱, Android 앱, HTML5 모바일 버전에서 사용해 보고 사용 방법을 알려주세요.