なぜReactは全部入りにならなかったのか?
AngularやEmberはフルフレームワーク。なぜReactはUIライブラリという選択をしたのか。その設計思想の本質に迫ります。
🤔 まず問いを立てる
ルーティング・データフェッチ・状態管理——
なぜReactはこれらを自分で提供しないのか?
React 2013年の登場当時、AngularはHTTPクライアント・ルーティング・テンプレート・サービス層を全て内包した「フルスタックフレームワーク」でした。 Facebookはなぜ逆の方向を選んだのでしょうか?
📜 Reactが生まれた文脈
Reactは2011年にFacebookの広告システムの問題を解決するために内部で作られました。 当時の課題は明確でした——複雑なUI状態の同期です。
Facebookが直面した問題
複数の場所に表示される通知数カウンター(メッセージ・コメント等)が、しばしば整合性を失っていました。 A地点で既読にしたのに、B地点では未読のまま——これはUI状態の同期問題でした。
Reactのチームは「問題の本質はUI状態の同期だ」と定義し、そこだけを解くという判断をしました。 ルーティングやHTTP通信は「別の問題」として切り離したのです。
⚖️ フルフレームワーク vs ライブラリの哲学
フルフレームワーク(Angular等)
- ✓ 全機能が最初から揃っている
- ✓ 公式の「正解」がある(規約重視)
- ✓ チームが統一した方法で書ける
- ✗ 一部を別のものに替えにくい
- ✗ フレームワーク全体のアップデートが必要
ライブラリ(React)
- ✓ 各層に最適なツールを選べる
- ✓ Reactコアの変更がルーターに影響しない
- ✓ React Native・React Three Fiberなど多様な環境で動く
- ✗ 「正解」を自分で選ぶ必要がある
- ✗ エコシステムの知識が必要
🧩 単一責任原則(SRP)との対応
Reactの設計は、ソフトウェア工学の単一責任原則(SRP: Single Responsibility Principle)とよく対応しています。
単一責任原則
「1つのモジュールは1つのことだけに責任を持つべきだ」——Robert C. Martin
ReactはUIレンダリングという1つのことに集中します。 ルーターはルーティングに、データフェッチライブラリはキャッシュ・同期に集中します。 各ライブラリが自分の問題領域を深く解くことで、エコシステム全体が進化できます。
// それぞれが「自分のことだけ」を深く解く React → UI状態 → DOM同期 React Router → URL ↔ UI TanStack Query→ サーバー状態 ↔ UI Zustand → グローバルUI状態 Tailwind → スタイリング
🔬 制約が生む可能性
Reactが「UIレンダリングだけ」に集中した結果、何が生まれたでしょうか?
React Native
Reactのコア(Reconciler)はDOMに依存していないため、iOSやAndroidのネイティブUIにも適用できました。 「UIライブラリ」という制約が、モバイルへの応用を可能にしました。 フルフレームワークではこの移植は困難だったでしょう。
React Three Fiber
Three.js(3Dグラフィックス)をReactのコンポーネントモデルで扱えるライブラリ。 ReactのReconcilerは「DOM操作」ではなく「差分計算」を担当しているため、 Three.jsのAPIを呼ぶRendererを実装するだけで利用できました。
Server Components
ReactはUIレンダリングに特化しているため、「サーバーでもクライアントでもコンポーネントをレンダリングする」という概念を フレームワーク層と協力して実現できました。 Reactがルーティングまで持っていたら、この設計は難しかったでしょう。
📈 変化に強い設計
フロントエンドの世界は急速に変化します。 Reactがコアを小さく保っているため、周辺エコシステムが独自に進化できます。
Reactは変わらず「UIレンダリング」だけを担当し続けました。周辺が変化し続けても、Reactのコアは安定していました。
📌 まとめ
- ✓ Reactは「UI状態の同期」という1つの問題を解くために生まれた
- ✓ 単一責任原則に沿って、Reactはそれ以外を担当しないと決めた
- ✓ 各ライブラリが自分の問題を深く解くことで、エコシステムが進化する
- ✓ コアを小さく保ったことで、React NativeやServer Componentsが実現できた
- ✓ 「正解を選ぶ自由」はコストでもあるが、変化への耐性でもある