と聞かれたので答えたことをまとめておく。
サーバサイドJavaScript
ものすごく大雑把で、しかも一部分でしかないが、とりあえずサーバサイドでやることをJavaScriptで書かせてくれるというのは事実。
JavaScriptのエンジンは山ほどあるが、NodeはV8 (Chromeのやつ) を使っている。1
なお、サーバサイドJavaScriptそれ自体はNodeの専売特許ではないし、Node.js最大の特徴はここではない。
利点
とりあえずJavaScriptだけやってれば書ける。
JavaScriptは簡便で、とりわけWeb屋であればやっていないほうがおかしい代物である。学習コストは非常に低い。
……もっとも、これはフロントエンドを十分やっている人間の理屈だ。
欠点
JavaScriptである。
JavaScriptは型が緩く、仕様がいろいろとガバガバで、ツール山盛りで書くものである……という先入観から地味に避けられやすい (ある程度事実だからこそタチが悪い) 。
"フロントエンドを十分やっている人間の理屈"って?
「Babel」「yarn」「CommonJS」などなどの "Modern JavaScript" を知らない、旧世代の骨董品のようなJavaScriptしか触っていないような(そう、普段はろくでもないJavaあたりのバックエンドをかいているような!)人間からすれば、Node.jsは完全に異次元である。
というか、「Node.jsってどういう言語なのか知ってる?」と大真面目に聞かれたことがある。引っ叩かずに済んだのは奇跡だろう。顔に呆れが出たのは流石に勘弁してほしい
そういった、「JavaScript? ああ、jQueryでしょ?」などと宣うような連中が割と珍しくない実情を鑑みると、「JavaScriptだから学習コストは低い」というのはかなり疑問である。
逆にそういった "Modern JavaScript" がわかるならなるほど低コストにもなろう、というわけで、まともにやってれば自然とそういったものに触れるだろう "フロントエンドを十分やっている人間" の理屈、という表現になる。
非同期I/Oとイベント・ドリブン
Node.jsの重要な特性。実際のところ、Node.jsがJavaScriptを選んだのはたまたまイベント・ドリブンでシングルスレッドだったからだろう。
イベント・ドリブン?
「ボタンが押された時音を鳴らす」という処理を書くとする……という話ではない。大抵「イベント・ドリブン」というとそっちなのだが、Nodeの話をする場合は少々事情が違う。サーバプログラムに関する話だからだ。
イベント・ドリブンである、とされないもの、つまりプロセス・ドリブンなんて呼ばれる――Apacheとか――ものは、お高いデパートの接客担当のようなものだ。客がやってくると生まれ、くっついて案内し、商品を探し、なんなら勘定までやって、そして死んで消えるか、再利用に備えて待機する。
このモデルは(プログラム上は)シンプルでわかりやすいが、客が増えると接客担当も増やさねばならないという欠陥がある。つまりクライアントが増えるとサーバのリソースが死ぬのだ。
この場合、店員とはコンピュータのプロセスないしスレッドであり、つまりは計算資源である。困ったことに必要な店員は接客担当だけではない。これが世にいうC10K問題2だ。
ではイベント・ドリブンなサーバプログラムはどうか。
イベント・ドリブンなサーバプログラムにおいて、接客担当は一人である。これは客が何十、何百、何千何万何億と詰めかけようとも変わらない。接客担当は一人で、延々と客をさばき続ける。
なんだそりゃ、ワンオペかなにかか?と思うかもしれない。恐ろしいことだがそのとおりである。イベント・ドリブン世界において接客担当はワンオペだ。プロセス・ドリブンと異なりいちいち生み出されたり殺されたりしない。全部同じ一人が延々繰り返す。
明らかに人手が足りない。遅くなるだけではないか? そう思うだろう。実際、そうなってしまっている実装も珍しくはない。問い合わせをかけてそのまま待つ時間は何もかもを止めねばならないのだから。
非同期I/O?
ここで非同期I/Oという概念が登場する。何も難しいことはない。先程ワンオペとは言ったがその実ワンオペでもなんでもないだけのことである。
昼飯時の牛丼屋に行ったことはあるだろうか。一人がレジ係で、注文を受ける。注文は厨房に伝えられる。厨房では逐次牛丼を作っている。レジ係は注文を伝えると牛丼を待たずに勘定を済ませ、なんなら「少々お待ちください」とだけ伝えて次の客の相手をする。
そう。誰かに任せて、できるだけ待たないのだ。「担当者に頼む」こと自体は非同期I/Oでなくともやるのだが、非同期I/Oの場合は更に「やれることはやれるところまで全部やる」のである。できることが無くなって初めて待つ。こうなると、接客担当すなわちプロセス/スレッドが1つでも大量の客すなわちリクエストを捌くことができる。一定量のリソースで大量のリクエストを捌けるのである。
Node.jsではこの非同期I/Oが強制されており、このため接客担当は一人でもフル稼働し、延々と新たな客の注文を聞き続けることができる。
つまりどういうこと?
- Node.js とはサーバプログラムである。サーバプログラムとは例えばApache, nginx, あるいはTomcatのような、「サーバ上で動いてWebアプリ乗っけたりするアレ」のことを意味している。
- Node.js はサーバプログラムだが、珍しい(唯一ではない)ことに処理内容をJavaScriptで記述する。これは特にフロントエンド民の参入障壁を下げる効果がある。ただしこれはオマケ程度だろう。
- Node.js はイベント・ドリブンで、非同期I/Oが強制されている。この形式は「一定量のリソースで大量のリクエストを捌く」ことに適合した形式である。