NodeJS – 범용 자바스크립트

자바스크립트

자바스크립트라는 단어를 들으면 가장 먼저 웹 브라우저를 연상하게 됩니다. 애초에 자바스크립트의 태생이 웹 브라우저였으니 당연한 것일지도 모르겠습니다.  그리고 웹의 부흥과 Ajax의 등장, 웹 어플리케이션에 대한 사용자의 요구가 맞물려 자바스크립트는 오늘날 가장 인기있는 언어 중 하나가 되었습니다.

2010년 2월 언어별 인기도

그런데, 이 정도의 위상에 맞지 않게 자바스크립트는 범용 언어로서는 그다지 두각을 나타내지 못했습니다. 서버 사이드 언어로 사용하려는 노력도 있었고(대표적으로 Jaxer), 데스크톱 응용 프로그램을 작성하기 위한 노력(Adobe AIR, XUL Runner 등)도 있었습니다. 하지만, 제가 원하는 것은 PHP, Perl, Python 등과 같이 쉘 스크립트는 물론, 원한다면 웹 서버도 작성할 수 있을 정도의 범용 스크립트였습니다.

물론, 그런 시도가 아예 없었던 것은 아닙니다.  Mozilla에서 만든 SpiderMonkey 엔진을 사용한 시도는 몇몇 있었지만,  범용 언어로 사용하기에는 성능이나 기능에 개선할 점이 많았습니다. 이 문제는 사실 SpiderMonkey 엔진 자체가 성능이 뛰어난 엔진은 아니었기 때문이기도 합니다. 이후 Mozilla에서는 Adobe의 도움으로 Tamarin이라는 프로젝트를 시작했고, 이 프로젝트와의 코드 공유를 통해 SpiderMonkey를 개선했습니다. 개선된 SpiderMonkey는 TraceMonkey라는 이름으로 Firefox 3.5 이상에 포함되었습니다. 아쉽게도 아직까지 TraceMonkey를 사용해서 자바스크립트를 범용적으로 만들려는 시도는 없습니다.

그 외에도 Safari에 사용된 Squirrel Fish, 구글 크롬에 사용된 V8 엔진이 있습니다. 특히 V8 엔진은 처음 나왔을 때 뛰어난 성능으로 주목을 받았었습니다. 오늘 소개할 NodeJS도 바로 V8 엔진을 사용했습니다.

NodeJS

간단하게 NodeJS는 자바스크립트를 Python 등의 언어처럼 범용적으로 사용하자는 목표를 가지고 있습니다. 화면에 Hello, world를 출력하는 *nix용 쉘 스크립트는 다음과 같이 작성할 수 있습니다.

var sys = require('sys');
sys.puts('Hello, world!');

그리고, /usr/local/bin/node hello_world.js와 같이 실행할 수 있습니다. 물론, Python이 그러하듯 파일 상단에 #!/usr/local/bin/node를 추가하면 ./hello_world.js와 같이 실행하는 것도 가능합니다.

NodeJS의 가장 큰 특징은 이벤트 기반의 작성 방법입니다. Perl이나 Python등도 비동기 이벤트를 사용해서 스크립트를 작성할 수 있지만, NodeJS처럼 기본 기능은 아닙니다. NodeJS는 대부분의 동작이 비동기 이벤트를 통해 이루어집니다. 간단한 예로 파일을 연다고 할 때, 다음과 같이 작성할 수 있습니다.

var fs = require('fs');
fs.open('sample.txt', 'r+').addCallback(function(){ ... });

참고로, Python에서는 다음과 같이 작성합니다.

openfile = open('sample.txt', 'r+')
openfile.read();
...

서버가 대용량 트래픽을 무리없이 처리하려면 이러한 비동기 I/O(혹은 Non-blocking I/O)는 필수에 가깝습니다. 그래서, 대다수 전통적인 언어들도 이러한 기능을 지원합니다. NodeJS는 이를 아예 기본 기능으로 삼았다는 점이 다를 뿐입니다.

예제

  • Hello, world
    var sys = require('sys');
    sys.puts('Hello, world!');
    
  • HTTP Server
    var sys = require('sys'),
        http = require('http');
    
    http.createServer(function (req, res) {
        setTimeout(function () {
            res.writeHeader(200, {'Content-Type': 'text/plain'});
            res.write('Hello World');
            res.close();
      }, 2000);
    }).listen(8000);
    
    sys.puts('Server running at http://127.0.0.1:8000/');
    

장점은?

  1. 이벤트 기반 I/O로 I/O관련 성능이 뛰어나며, 특히 네트워크 프로그래밍에 좋습니다.
  2. 자바스크립트는 상당히 보편적인 언어입니다. 웹 개발자라면 자바스크립트 한 번 안 건드려본 사람이 없을 것입니다. 웹 개발 언어로 자바 진영이 많다, PHP 진영이 많다, 혹은 ASP(.NET 포함)쪽이 많다라고 하지만 (아마도) 가장 많은 개발자 풀은 앞선 진영들의 합집합인 자바스크립트 쪽에 있습니다. 다른 스크립트 언어를 배우는 노력보다 훨씬 적게 들 것입니다. 한 사람의 자바스크립트 개발자만 있으면 서버와 클라이언트를 모두 아우를 수 있습니다.

  3. 대형 벤더가 지원하는 자바스크립트를 사용합니다. 자바스크립트는 나날이 빨라지고 있습니다. 오페라같은 상대적으로 작은 회사부터 모질라 재단을 거쳐 애플, 구글, MS 같은 큰 회사들에 이르기까지 자바스크립트를 빠르게 만들기 위해 노력하고 있습니다. 또한, 그 중 많은 부분이 오픈 소스로 진행되고 있습니다. 현재 사용하고 있는 V8 엔진의 성능이 부족하다 느낀다면 더 빠른 다른 엔진으로 갈아타도 그만입니다. 그래도 스크립트를 다시 작성할 필요가 없습니다.

  4. 성능이 필요한 부분에는 C++로 작성한 확장 기능을 추가할 수 있습니다. 많은 스크립트 언어들이 가지는 특징이기도 합니다.

  5. 상당히 유연합니다. 자바스크립트 언어에 대한 내용이지만, 사실 기본 객체마저 확장하거나 재정의할 수 있습니다.

단점은?

  1. 대부분의 스크립트 언어가 그렇듯, 제 아무리 빠른 스크립트 언어라도 C, C++ 등과 같이 직접 컴파일한 언어의 속도에 비할 바는 못됩니다. 하지만, 이는 모든 스크립트 언어가 같은 문제를 가지고 있으므로 딱히 단점이라고 말하기는 힘들 것 같습니다.

  2. 역사가 오래되지 않다 보니 아직 지원하는 컴포넌트가 별로 없습니다. Perl, Python, PHP 등이 자랑하는 엄청난 양의 확장 기능에 비하면 거의 없는 것이나 마찬가지일 정도입니다.

  3. 지나치게 유연합니다. 기본 객체마저 삭제할 수 있는 자바스크립트의 지나친 유연함은 일부 개발자들에게는 단점으로 작용하기도 합니다.

미래는?

NodeJS에 대해서 열심히 홍보했지만, 정작 그의 장래성에 대해 물으면 ‘글쎄요’라고 말할 수 밖에 없습니다. 분명 자바스크립트는 제가 가장 좋아하는 언어이고, 가장 자신있게 사용할 수 있는 언어임에는 틀림없지만 아직까지 NodeJS의 성능이나 기능에 대해서는 이렇다할 확신을 가지기에는 조금 이르다는 느낌입니다.

우선, 벤치마킹 자료가 별로 없습니다. 정확히 성능은 어느 정도인지, 얼마나 잘 견뎌주는지에 대한 자료가 없어 보수적인 분들이 무작정 믿고 쓰기에는 불안할 수 있습니다. 특히, 실험적이지 않은 현재 운영중인 서비스에 적용하고 싶다면 더욱 망설여지는 것도 사실입니다. 뿐만아니라 확장 기능이 거의 없다시피 한 점은 큰 단점으로 작용하죠(심지어 간단한 이미지 처리조차 할 수 없습니다).

그럼에도 불구하고 NodeJS는 꽤 매력적입니다. NodeJS 이전에도 비슷한 시도들이 많았다는 사실은 이러한 방식이 꽤 매력적이라는 것을 방증합니다. 아마 앞으로도 이러한 시도는 계속 될 것이라 생각합니다. NodeJS를 사랑하는 능력있는 개발자들이 컴포넌트를 빠르게 많이 개발해주고, 성능에 대한 검증이 이루어진다면(간단히 테스트 해본 결과 성능은 괜찮다고 보입니다) 꽤 경쟁력이 있을 것이라 생각합니다.

그러나 발전여부와 상관없이 자바스크립트를 주 언어로 삼고 있는 개발자 입장에서는 상당히 매력적인 언어임에는 틀림없습니다.

덧 // 참고로 성능 측면에서 최근 NodeJS를 도입한 Plurk의 개발자에 따르면, Java+Jetty를 사용하는 것보다 NodeJS를 사용해 Comet을 구성하는 편이 메모리 효율이 10배 이상 좋았다고 합니다.

  1. “이벤트 기반 I/O로 I/O관련 성능이 뛰어나며,” 에 대한 뒷바침되는 근거 자료가 있으면 좋을 것 같아요. 비교 자료 같은 것이요.

    comet 구성에는 확실히 좋은 것 같네요. jetty 에 비해 메모리 효율이 10 배 이상 좋다고 하고, 작성할 코드도 간단 명료해 보이고요. :]

    크롬의 V8 엔진을 맹신하고 있는 저는 매력적인 성능이 기대되는군요. :]

    다만 확장기능이 거의 없다는 점이 너무 아쉽네요.

    확장기능에 대한 프로젝트를 해도 괜찮을듯한..

    1. 일반적으로 비동기 I/O가 동기 I/O보다 CPU 사용이나 효율측면에서 더 좋다고 알려져있어서 별도로 근거를 달지 않았습니다. ^^
      개인적으로는 NodeJS가 상당히 마음에 들어서 확장 기능을 하나씩 만들어갈까 합니다. ㅎㅎ

  2. 기존 자바스크립트의 단점, 쓸데없이 타입쳐야된다는것이 너무 많다는 것이 좀 단점같습니다.
    fopen같은 간단한 함수같은것이 있었으면 좋겠네요.
    확장기능은 지금 github 내에 계속 생겨나고 있던걸로 알고 있습니다.

Leave a Reply