programming/node.js2013.04.05 16:12

linkedin에서 근무하는 개발자가 쓴 Node.js 성능 향상을 위한 10가지 팁을 대충 번역해봤습니다.

linkedin에서 모바일 서비스 부분을 Node.js로 개발 한 후 얻은 경험을 정리 한 것 같네요.

직역이 아니고 번역이라, 조금 제 의견도 첨부했습니다.

출처 : http://engineering.linkedin.com/nodejs/blazing-fast-nodejs-10-performance-tips-linkedin-mobile


1. 동기식 코드(Synchronous code)를 피하라

Node.js는 아시다시피 프로세스당 싱글스레드로 돌아갑니다. 즉, 동기식 코드를 짠다면 동기화를 하기 위해 순간적으로 블러킹이 발생하므로 성능에 문제가 생기게 됩니다. Node.js는 모든 함수들이 기본적으로 비동기를 지원하게 되어있습니다. 고로 event기반 코드를 이용하여 비동기 프로그램을 짜는게 성능에 좋습니다.

// 비동기식 코드 : 성능이 좋다
fs.writeFile('message.txt', 'Hello Node', function (err) {
console.log("It's saved and the server remains responsive!");
});
 
// 동기식 코드 : 블러킹이 발생하면 성능에 안좋다
fs.writeFileSync('message.txt', 'Hello Node');
console.log("It's saved, but you just blocked ALL requests!");
그런데 비동기식으로 코드를 짰더라도 블러킹 문제가 생길 수 있는 경우가 있습니다.

예를 들어 비동기식으로 특정 파일에 쓰기를 하려는데, 해당 파일을 다른 서드파티 라이브러리나 프로세스가 점유하고 있을 경우 같이 말이죠. 블러킹을 피하려면 여러 가능성 있는 시나리오들을 예상해서 대비하는게 좋습니다.



2. 소켓풀링(Socket Pooling)을 꺼라

Node.js의 Http Client는 소켓풀링을 기본적으로 사용하게 되어있습니다. 쉽게 말해 소켓 연결이 끊어져도 리소스를 완전히 해제시키지 않고 나중에 클라이언트가 접속하면 재사용함으로서 리소스를 재활용 하겠다는 뜻이죠. 그런데 수많은 동시요청을 처리해야 하는 경우엔 소켓풀링이 오히려 심각한 병목현상을 초래 할 수 있습니다. 이런 경우엔 소켓풀링 옵션을 해제하거나 maxSockets 값을 늘리는게 좋은 방법입니다.

// Disable socket pooling
var http = require('http');
var options = {.....};
options.agent = false;
var req = http.request(options)


3. 정적 리소스는 CDN이나 다른 서버를 이용하라

CSS나 이미지 같은 정적 리소스들은 Node.js 서버 대신에 다른 웹서버를 쓰는게 좋습니다. 이건 Node.js 뿐만아니라 모든 웹 어플리케이션 서버도 마찬가지죠. 웹개발자라면 다 아시겠지만 정적 리소스들을 CDN에 올릴 경우 Node.js서버의 부하도 줄일 수 있고, 유저들도 비교적 빠른 서버로부터 리소스들을 받을 수 있으므로 누이좋고 매부좋은 일이죠.



4. 서버사이드의 렌더링을 최소화 하라

일반적으로 웹프로그래밍은 서버사이드 코드의 결과가 HTML로 변환된 후 클라이언트로 전송되게 됩니다. 이 과정에서 서버측에서 다이내믹하게 바뀌는 값이 아닌, 이를테면 디자이너들이 디자인한 정적인 HTML들도 함께 렌더링 되어 전송되게 됩니다. 여기서 발생하는 HTML렌더링 비용을 서버가 아닌 클라이언트에게 부담 시키자는거죠. 

예를 들어 다음과 같은 asp 코드가 있다고 치면


<!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>


<%= name %> 을 제외하고는 모두 정적인 데이터들입니다. 그런데 웹서버는 저 많은 HTML들을 렌더링 하므로 name값만 렌더링 하는것 보다 비용이 더 들게 됩니다. 그러나 Ajax같은걸 이용하여 name만 따로 받는다면? 이러면 정적인 HTML들과 동적인 데이터를 분리 할 수 있게 되고, 정적인 HTML들은 .html 파일로 만들어 CDN에 올릴 수도 있습니다. 웹서버는 이제 순전히 동적인 데이터들만 신경쓰면 되는거죠.

이런 작업들을 조금 손쉽게 하기 위해 원글 작성자는 underscore.js라는 자바스크립트 템플릿 엔진을 추천하고 있습니다. (backbone같은 자바스크립트기반 MVC모델 프레임워크도 좋습니다!)


5. gzip을 사용해라

뭐 이것도 node.js 뿐만 아니라 모든 웹서버에 해당되는 얘기인데, http 데이터를 gzip으로 압축하라는 얘기입니다. 

이 영문 원글은 모바일용 웹서버를 Node.js로 따로 만든 케이스를 가지고 얘기 하고 있기 때문에, 아래 그림 같이 클라이언트 뿐만 아니라 Backend Server들과 통신시에도 gzip 압축을 하라고 설명하고 있습니다.

Use gzip


6. 병렬처리를 하라

원격 서버와 통신, DB 연결, 파일 쓰기 같은 블러킹이 발생하는 작업이 있는 경우, 병렬적으로 동시에 처리하도록 하세요. 각각 요청을 하나씩 수행했을 때 걸리는 부하보다 동시에 처리하는게 부하가 덜 든다고 합니다. 트랜잭션 처럼 각각의 요청들을 한번에 콜백하거나 에러처리 해야할 경우는 Step 같은 flow control 라이브러리를 사용해 보세요.

Make blocking calls in parallel


7. Session을 줄여라

Node.js에서 많이들 쓰시는 express framework 같은 경우, 기본적으로 세션 데이터 저장에 메모리를 사용하고 있습니다. 유저가 많아지면 많아질 수록 메모리에 부담이 가게 됩니다. 다행히도 express는 외부 세션 저장소를 선택 할 수 있는데, MongoDB나 Redis같은 별도 서버를 세션 저장소로 사용하면 메모리를 아낄 수 있습니다. 하지만 네트워크 부하는 조금 늘어나겠죠. 어쨌든 최대한 서버가 상태값을 가지는 것을 최소화 하라는 게 중요하답니다.



8. 바이너리 모듈을 사용해라

가능하면 자바스크립트 모듈보다는 Node.js로 컴파일된 모듈을 사용하라고 합니다. 저자가 처음에 자바스크립트로 된 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 자바스크립트 엔진을 써라

아시겠지만 자바스크립트는 클라이언트 사이드인 웹브라우저에서 돌아가는 언어입니다. 웹브라우저가 다양하다보니 지원하는 자바스크립트 라이브러리도 각양각색이죠. 여기서 Node.js는 구글의 V8 엔진을 사용했으므로, 가능하면 V8엔진에 호환되는 자바스크립트 라이브러리를 사용하는게 성능향상에 도움이 됩니다. V8 엔진은 ECMA-262, 5 edition을 표준으로 구현했으므로 스펙 문서를 보시는 것도 도움이 될거에요.


10. 코드를 짧고 간결하게 짜라.

모바일 환경은 데스크탑에 비해 훨씬 가볍게 구현하는게 좋습니다. 따라서 이런저런 모듈을 갖다 붙이기 보다는 진짜로 필요한 모듈만 설치하고 가능한 간결하게 만들도록 해보세요. 작고 가벼운 코드가 일반적으로 빠르고 효과적이니까요.



Node.js 최적화 방법이긴 하지만 대부분 일반 웹이나 어플리케이션에서도 공통적으로 필요한 설명도 있었습니다. 아무쪼록 성능향상에 도움이 되었기를 바랍니다. 이만!

저작자 표시 동일 조건 변경 허락
신고
Posted by 귀뫄뉘

댓글을 달아 주세요

  1. 검색하다 보니 들어왔네... 역시!!! +_+)b

    2013.05.15 17:38 신고 [ ADDR : EDIT/ DEL : REPLY ]
  2. 카비

    좋은 정보 감사합니다!

    2013.05.17 02:26 신고 [ ADDR : EDIT/ DEL : REPLY ]
  3. 곰발가락

    좋은 글 소개 감사합니다. :)

    2013.05.24 15:14 신고 [ ADDR : EDIT/ DEL : REPLY ]


티스토리 툴바