OS、JavaScript、Node.js、npm、Next.js。
それぞれ別の話に見えて、実は一本の積み木として重なっています。
設計する側が、その積み木の並びを知っておくための資料です。
AI が得意な領域と、人間にしか残らない領域は、はっきり分かれています。
AI が強いのは真ん中です。実装、記法、定型的な処理。ここは速く、質も高い。
弱いのは両端です。
要件、制約、優先順位、許容できるリスク。これは外から与えるしかありません。AI は事務所の業務も、顧問先の事情も、来年の制度改正の見込みも知りません。何を作るべきか、そして何を作るべきでないかは、外部から入力される情報でしかない。
AI は自信を持って間違えます。しかも、間違え方が自然です。検算できない人は、間違いをそのまま本番に入れます。
「なんか動きません」としか言えない状態と、「Node のプロセスが 3000 番ポートを掴んだまま終了していない」と言える状態では、返ってくるものがまるで違います。前者に対して AI は推測するしかない。後者なら一手で解決します。
言葉を持っているかどうかが、そのまま解像度になります。土台を知るというのは、知識を蓄えることではなく使える語彙を増やすことだと考えるほうが実態に近いと思います。
ここは正直に書いておきます。抽象化の階層が上がるほど、下の層を知らずに作れる範囲は確実に広がっています。アセンブリを知らなくても優れた Web アプリは作れますし、CPU の命令セットを知らないことが欠陥になる場面はほとんどありません。
問題は知識の量ではなく、どこまで降りられるかです。普段は一番上の層で作業していい。ただし詰まったとき、一段ずつ下へ降りて「ここは正常、ここも正常、ここが怪しい」と切り分けられること。この能力が差になります。
設計とは、無数にある選択肢のうち、どれを採用しどれを捨てるかを決めることです。
捨てる判断には、捨てたときに何が起きるかの理解が要ります。AI は選択肢を並べることはできますが、責任を負う人間の代わりに捨てる判断はできません。並べるのは AI、決めるのは人間という分担は、当面変わらないと思います。
Operating System、日本語では基本ソフト。すべての土台です。
OS が無かった時代、プログラムは機械そのものを直接操作していました。プリンタの型番が変われば、すべてのプログラムを書き直す必要がありました。
OS の役割は二つに集約されます。仲介と抽象化です。プログラムとハードウェアの間に立ち、複数のプログラムが同じ機械を奪い合わないよう調停し、面倒な違いを覆い隠して統一的な形で見せる。
ここが本質だと思います。OS はそれぞれのプログラムに対して、「この機械はお前専用だ」と思い込ませています。実際には数百のプロセスが同じ CPU とメモリを奪い合っているのに、各プログラムは自分だけが動いていると信じたまま動いています。
CPU については時分割という手法を使います。1つの CPU が数ミリ秒ごとに担当を切り替える。切り替えが速すぎるので、人間には同時に動いているように見えます。
メモリについては仮想メモリを使います。各プログラムに「0番地から始まる自分専用の広大な空間」があるように見せかけ、実際の物理メモリ上のどこに置くかは OS が裏で管理します。
この二つの嘘があるから、私たちはブラウザとエディタとターミナルを同時に開けます。
OS の内部はカーネル空間とユーザー空間に分かれています。アプリはユーザー空間で動き、ハードウェアには直接触れません。触りたければシステムコールという窓口を通す必要があります。
面倒に見えますが、これは安全装置です。一つのアプリのバグでシステム全体が巻き添えになるのを防いでいます。アプリが落ちても OS は生きている、という当たり前の状態は、この壁が作っています。
| OS | 系譜 | 主な用途 |
|---|---|---|
| Unix(1969) | すべての源流 | 研究機関・大型機 |
| Linux(1991) | Unix の思想を独自に再実装 | サーバーの大半・Android・Vercel の実行基盤 |
| macOS | BSD 経由で Unix の直系 | 個人・開発 |
| Windows | MS-DOS 由来の別系統 | 企業の事務端末 |
macOS が Unix の直系であることが、実務上そのまま効いてきます。Mac のターミナルで Linux 向けの手順がほぼそのまま動くのは、血縁があるからです。Windows で同じ手順が動かないのは、家系が違うからです。
1995年、ブラウザの中でちょっとした動きをつけるために、約10日で作られた言語です。
Netscape という会社の Brendan Eich が設計しました。当時の目的は控えめなもので、「ボタンを押すと色が変わる」「入力欄が空なら警告を出す」といった程度の仕掛けを想定していました。
JavaScript と Java はまったく別の言語です。血縁も互換性もありません。当時人気だった Java にあやかった、商標上の判断による命名です。「インドとインドネシアくらい違う」という言い方がされます。
理由は一つです。世界中のあらゆるブラウザに、最初から入っている唯一の言語だからです。
他の言語でブラウザを動かそうとすれば、利用者にインストールを求める必要があります。JavaScript にはその手間がありません。この一点だけで、他の選択肢を退けました。技術的な優劣ではなく、置かれた場所が勝敗を決めた例です。
| 言葉 | 意味 |
|---|---|
| ECMAScript | JavaScript の正式な規格名。ES2015 などのバージョン表記はこれを指す |
| TypeScript | JavaScript に「型」の指定を足したもの。書いた時点で間違いに気づける。最終的には JavaScript に変換されて動く |
| .js / .ts / .jsx / .tsx | 拡張子。x が付くものは、後述の React の記法を含むファイル |
TypeScript は、AI と組んで開発する場合とくに効きます。型が書いてあると、AI が生成したコードの誤りをその場で機械が検出できるためです。人間の検算を機械が肩代わりしてくれる範囲が広がります。
JavaScript を、ブラウザの外に連れ出したものです。
2009年、Ryan Dahl という技術者がやったことは、一言で言えばこうです。Google Chrome の中で JavaScript を動かしている部品(V8 エンジン)を取り出して、単体で動くようにした。
これによって JavaScript が、ブラウザの外 ─ つまり普通のコマンドラインプログラムとして、そしてサーバーとして動くようになりました。画面側と裏側を同じ言語で書ける、という現在の状況はここから始まっています。
Node.js は言語ではありません。JavaScript という言語を動かすための実行環境(ランタイム)です。「Node で書く」という表現は、正確には「JavaScript で書いて Node で動かす」ということです。
ターミナルで node app.js と打つとき、何が起きているか。第1部の第4章がそのまま当てはまります。
bash が PATH から /usr/bin/node を探し、自分の複製を作り、その中身を node のプログラムで上書きする。node が起動するプログラムで、app.js はそこへ渡されるただの引数です。app.js 自体が起動しているわけではありません。
サーバーとして起動した Node は、終わらないことが仕事です。リクエストが来るのを待ち続けるために、意図的に終了しません。
だから Ctrl+C で止めるか、明示的に kill しない限り生き続け、ポートを掴んだままになります。「なぜか 3000 番が使用中」の正体はこれです。異常ではなく、設計どおりの挙動が残っているだけです。
Node Package Manager。他人が書いた部品を取り寄せる仕組みです。
日付の整形、パスワードの暗号化、CSV の読み込み、PDF の生成。こうした処理は、世界中で毎日誰かが書き直しています。同じものを何度も作るのは無駄です。
npm は、誰かが作って公開した部品(パッケージ)を、1行で自分のプロジェクトへ持ってこられるようにする仕組みです。
| ファイル | 役割 | 誰が書くか |
|---|---|---|
package.json | 部品表。何が必要かを列挙する | 人間(と npm) |
package-lock.json | 実際に入った正確なバージョンの記録 | npm が自動生成 |
node_modules/ | ダウンロードされた部品の置き場 | npm が自動生成 |
package.json はテキストファイルです。人が読めて、機械も読めて、Git で差分が見え、AI にもそのまま渡せる。第1部の原則4「テキストを共通語にする」が、そのまま実装されています。
部品が、別の部品を必要とするからです。そしてその部品が、また別の部品を必要とする。この連鎖が数段続くと、自分で指定したのは3個でも、実際には数百のパッケージが入ります。
これは無駄ではなく、原則2「一つのことをうまくやる」の帰結です。各部品が小さく作られているからこそ、数が増えます。
| コマンド | 何が起きるか |
|---|---|
npm install | 部品表を見て、必要なものを全部取り寄せる |
npm install パッケージ名 | 新しい部品を1つ追加し、部品表にも書き足す |
npm run dev | package.json の scripts に書かれたショートカットを実行する |
npm ci | lock ファイルどおりに厳密に再現する。本番やビルド環境向け |
npm run dev は、それ自体が何かをするコマンドではありません。package.json に書いてある別のコマンドを呼び出しているだけです。上の例なら、実際に動くのは next dev です。
npm でパッケージを入れるということは、他人が書いたコードを自分の製品に取り込むということです。依存が増えるほど、内容を確認していないコードの割合が増えます。
「その部品は本当に必要か。自分で20行書けば済むものではないか」。この判断は AI に委ねられません。顧客データを扱うのか、どこまでの停止が許容されるのか、といった文脈を持っているのは人間だけだからです。
順番に見ていきます。Next.js は React の上に乗っているので、React が先です。
Facebook が作った、画面を組み立てるためのライブラリです。発想はシンプルで、画面を部品(コンポーネント)の組み合わせとして作ります。
ボタン、入力欄、表、カード。それぞれを独立した部品として書き、必要な場所に置いて組み立てる。同じボタンを10箇所で使うなら、書くのは1回です。
これは第1部の原則2「一つのことをうまくやる」と、原則3「組み合わせて使う」を、そのまま画面作りに持ち込んだものです。Unix が小さなコマンドを組み合わせたように、React は小さな部品を組み合わせます。
React だけでは足りないものが、実務ではたくさん出てきます。URL とページの対応づけ、表示速度の最適化、本番用にコードを固める作業。Next.js はそれらをまとめて引き受ける枠組みです。
ライブラリは、自分が呼ぶものです。必要なときに手を伸ばす道具箱。
フレームワークは、自分が呼ばれるものです。決まった場所に決まった名前でファイルを置いておくと、向こうから呼びに来ます。
「こちらから連絡しないでください、こちらからかけます」というオーディションの決まり文句になぞらえて説明されることがあります。主導権がどちらにあるかが逆転している、というのが要点です。
| 機能 | 内容 |
|---|---|
| ルーティング | app/about/page.tsx に置くと /about という URL になる。置き場所がそのまま URL |
| サーバー側描画 | 画面をサーバーで組み立ててから送る。表示が速く、検索エンジンにも読まれる |
| ビルド | 開発用のコードを、本番用に圧縮・最適化して固める |
| 画像の最適化 | 閲覧環境に応じたサイズと形式で自動的に配信する |
「ファイルを置くと URL になる」という設計は、第1部の原則1「すべてはファイルである」の直系です。半世紀前の発想が、そのまま現代のフレームワークの中で生きています。
Next.js を作っている会社が Vercel です。自社で設計したフレームワークを、自社の実行基盤の上で動かしている。だから git push するだけで公開まで進みます。相性が良いのは当然で、同じ会社が両側を設計しているためです。
裏返せば、Vercel 以外で Next.js を動かす場合には、その連携部分を自前で用意する必要が出てきます。これも設計判断の一つです。
ここまで出てきたものを、一枚に積み上げます。
各層には共通の性質があります。下の層に依存し、上の層に対しては複雑さを隠すということです。
Next.js を書いている間、CPU の時分割を意識することはありません。それが抽象化の目的です。意識しなくていいから、上の層の仕事に集中できる。
ただし、隠されているだけで、無くなってはいません。普段は見えない下の層が、問題が起きたときにだけ姿を現します。そのとき、そこに何があるかを知っているかどうかで対応が変わります。
この7層は、そのまま「誰が責任を持つか」の区分でもあります。
ハードウェアからシェルまでは、OS の作り手の責任。Node.js と npm の部品は、その公開者の責任。Next.js は Vercel の責任。そして一番上の層だけが、あなたの責任です。
依存を増やすということは、他人の責任範囲を増やすことでもあります。楽になる代わりに、自分でコントロールできない部分が増える。この取引を意識的に行えるかどうかが、設計の質を分けます。
層構造を知っている実利は、ほぼここに集約されます。
原則は一つです。下から上へ確認する。上の層で悩む前に、下の層が正常であることを確かめる。下が壊れていれば、上で何をしても直りません。
| 症状 | 疑う層 | 確認方法 |
|---|---|---|
| コマンドが見つからない | シェル / PATH | which node で場所を確認 |
| ポートが使用中 | OS / プロセス | lsof -i :3000 で犯人を特定 |
| npm install が失敗する | npm / ネットワーク | エラーの最終行を読む |
| 起動はするが画面が白い | 自分のコード | ブラウザの開発者ツールのコンソール |
| ローカルは動くが Vercel で落ちる | 環境差 | Node のバージョン、環境変数、ビルドログ |
| 昨日まで動いていた | 依存関係 | lock ファイルの差分を確認 |
切り分けができていると、AI に渡す情報の質が変わります。
後者に対して AI は、Vercel 側の環境変数設定が抜けているという結論に一手で到達します。前者に対しては、可能性を10個並べることしかできません。
ここで効いているのは技術力ではなく、どの層で止まったかを言語化する能力です。
この資料の内容を全部覚える必要はありません。層の名前と並び順、そして「困ったら一段下を疑う」という手つきさえ身についていれば十分です。
実装は AI が速い。ならば人間が持つべきは、何を作るかを決める力と、出てきたものを疑う力です。そのどちらも、土台の構造を知っていることを前提にしています。