Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

node.js는 무엇인가? #1

그동안 봐야지 봐야지 하던 Node.js를 이제야 보기 시작했습니다.


간단히 말하면 Node.js는 서버사이드에서 동작이 가능한 Javascript이지만 보통 서버사이드 자바스크립트라고 하면 생각할만한건 runat="server"같은 수준의 서버사이드 자바스크립트와는 차원자체가 다릅니다. 또한 Jaxer나 Narwhar같은 서버스크립트 자바스크립트 환경도 존재하지만 Node.js는 약간 다릅니다. 원래는 nettues+의 Learning Server-Side JavaScript with Node.js를 따라하면서 포스팅을 하려고 하였지만 Node.js를 만든 Ryan DahlJSConf 2009에서 발표한 동영상을 보는 것이 훨씬 이해하기가 좋아서 Ryan Dahl의 발표영상을 링크합니다.


Ryan Dahl: Node.js

동영상에 나오는 발표자료는 글자가 잘 보이지 않아서 Scribd에 올라와 있는 발료자료입니다. (JSConf정도 행사에 node.js같은 프로젝트를 들고 나오는 사람이 헤져서 글자도 잘 보이지 않는 나이키티셔츠를 걸치고 나와서 한다는 것이 재밌기도 하네요.)


Node.js JSConf 2009


Node.js는 서버사이드 자바스크립트이며 Google의 자바스크립트 엔진인 V8이 빌트인되어 있습니다. Event 기반이며 non-blocking I/O를 지원합니다. 자바스크립트의 표준라이브러리 프로젝트인 CommonJS의모듈시스템을 지원합니다.

Apache같은 웹서버들은 모든 요청마다 시스템 쓰레드를 생성하는 쓰레드 기반이고 대부분의 경우에는 잘 동작하지만 Friendfeed나 Google Wave같은 리얼타임 애플리케이션처럼 많은 long-lived커넥션을 사용하는 애클리케이션에는 적합하지 않고 확장(scale)하기가 어렵습니다. 위 프리젠테이션에서 Apache와 NGINX를 비교한 그래프를 보면 쓰레드기반인 Apache는 요청이 늘어날수록 메모리가 증가하지만 NGINX는 직선을 유지하는 것을 볼 수가 있습니다. 이는 NGINX는 Event Loop를 사용하기 때문입니다.

이런 쓰레드기반의 문제를 Event Loop를 이용하면 해결할 수 있습니다.(여기서 Event Loop라는 것은 동작을 요청한뒤에 콜백을 지정하여 동작이 완료되면 콜백이 실행되는 방식을 발합니다.) 그럼 왜 모두가 Event Loop를 사용하지 않는가하는 의문이 생깁니다.

node.js 로고


Ryan Dahl은 문화적인(Cultural) 이유와 구조적(infrastructural)인 이유 2가지가 있다고 생각하였습니다.


문화적인 이유는 우리가 프로그래밍을 배울때 인풋을 요청하면 요청한 인풋을 받을때까지 아무것도 하지 말라고 배웠기 때문입니다.

puts("Enter your name: ");
var name = gets();
puts("Name: " + name);

위 코드는 인풋을 받아서 출력하는 익숙한 코드입니다. 인풋이 들어올때까지 아무것도 행하지 않습니다.

puts("Enter your name: ");
gets(function(name) {
    
puts("Name: " + name);
});

이벤트 루프방식인 위와같은 코드는 복잡하다는 이유로 거부되어 왔습니다.

구조적인 이유는 싱글쓰레드이벤트 루프는 논블럭킹 I/O를 요구하지만 대부분의 라이브러리들은 그렇지 않았습니다. POSIX I/O나 DB라이브러리들은 비동기요청을 지원하지 않았습니다. 하지만 현재는 EventMachine, Twisted등 좋은 이벤트루프 플랫폼이 존재하고 있지만 사용자들은 어떻게 다른 라이브러리들과 이것들은 조합할수 있을지 혼란스러워 하고 있으며 서버사이드 개발자들은 이벤트 루프와 넌블락킹 I/O에 대한 지식이 필요합니다.

하지만 Javascript는 Event Loop를 사용하도록 디자인되어 비동기 펑션과 클로져를 지원하고 한번에 하나의 콜백만 실행하며 DOM 이벤트 콜백을 통한 I/O를 지원하고 있습니다. 더군다나 자바스크립트의 문화는 이미 이벤트기반의 프로그래밍에 익숙해져 있습니다.



Design Goal
  • Function은 직접 플랫폼 I/O에 접속하지 않습니다.
  • Disk, network, 프로세스를 통해 데이터를 받기 위해서는 반드시 콜백(callback)을 사용합니다.   콜백을 사용할 수도 있습니다. (함수명sync()라는 함수들이 제공되고 있다는 AJ님의 제보에 따라 수정하였습니다. 위 PT의 28페이지에 must be라는 표현으로 보아 보통의 경우 callback을 권장하는 것으로 추측(?)됩니다.)
  • TCP, DNS, HTTP같은 프로토콜을 지원합니다.
  • HTTP feature를 지원합니다.(Chunk된 requst/response, Keep-alive, Comet을 위한 리퀘스트 홀딩
  • 클라이언트 사이드 자바스크립트 프로그래밍과 과거 학생때 배운 Unix 스타일에 친숙하게 디자인되었습니다.



Internal Design
  • Google의 V8 사용
  • Marc Lehmann이 만든 이벤트루프 라이브러리 libev 사용
  • Marc Lehmann이 만든 쓰레드풀 라이브러리 libeio 사용
  • Ryan Dahl이 만든 HTTP파서 http-parser 사용
  • Ryan Dahl이 만든 libev에 기반한 스크림 소켓 라이브러리 evcom 사용
  • Michael Tokarev가 만든 넌블럭킹 DNS resolver udns 사용


더 자세한 내용은 AJ님의 core perspective to node.js를 참고하시면 도움이 될 것입니다.



이 포스팅은 node.js는 무엇인가? #2 : Hello World 실행하기로 이어집니다.
2010/06/06 23:12 2010/06/06 23:12