React 概要
React は、モダンな Web アプリケーションの UI を構築するための JavaScript ライブラリです。 この章では React の基本的な考え方、仮想 DOM、コンポーネント指向、SPA の概念を理解し、 従来の開発手法との違いを学びます。
React とは何か
React(リアクト)は、Meta(旧 Facebook)が 2013 年にオープンソースとして公開した ユーザーインターフェース(UI)を構築するための JavaScript ライブラリです。 Facebook、Instagram、Netflix、Airbnb など世界中の大規模サービスで採用されており、 フロントエンド開発のデファクトスタンダードの一つとなっています。
React の大きな特徴は以下の 3 つです。
- 宣言的 UI — 「どのような画面にしたいか」を記述するだけで、React が差分を計算して DOM を更新する
- コンポーネント指向 — UI を独立した部品(コンポーネント)に分割し、再利用・テストしやすくする
- 仮想 DOM — メモリ上の軽量な DOM 表現を使い、最小限の実 DOM 操作で高いパフォーマンスを実現する
React は「ライブラリ」であり「フレームワーク」ではありません。 ルーティングや状態管理などは含まれておらず、必要に応じて別のライブラリ(React Router、Redux など)を組み合わせます。 一方、Angular や Vue.js はより多くの機能を内蔵したフレームワークです。
宣言的 UI
React を理解するうえで最も重要な概念が 宣言的 UI(Declarative UI) です。 従来の DOM 操作(jQuery など)では「どうやって画面を変えるか」を手続き的に書きましたが、 React では「今のデータに対して画面がどう見えるべきか」を宣言的に記述します。
命令的 vs 宣言的
まずは jQuery(命令的アプローチ)で「いいねボタン」を実装してみましょう。
// jQuery: 命令的に「どう変更するか」を記述
let count = 0;
$('#like-btn').on('click', function() {
count++;
$('#like-count').text(count); // テキストを手動で更新
if (count > 0) {
$('#like-btn').addClass('active'); // クラスを手動で追加
}
});
同じ機能を React(宣言的アプローチ)で書くとこうなります。
import { useState } from 'react';
function LikeButton() {
const [count, setCount] = useState(0);
return (
<button
className={count > 0 ? 'active' : ''}
onClick={() => setCount(count + 1)}
>
いいね {count}
</button>
);
}
jQuery 版では「テキストを更新し、クラスを追加する」という 手順 を書いています。 React 版では「count の値に応じて画面はこう見えるべき」という 状態と見た目の関係 を書いています。 React が状態の変化を検知し、必要な DOM 更新を自動で行ってくれるため、 開発者は UI の「あるべき姿」だけに集中できます。
宣言的 UI の利点は、状態が複雑になるほど顕著になります。 命令的なコードでは状態の組み合わせごとに DOM 操作が必要ですが、 宣言的なコードでは「データ → 画面」の対応を一度定義すればよいため、バグが入り込みにくくなります。
仮想 DOM
ブラウザの DOM(Document Object Model) は、HTML をツリー構造で表現したものです。 JavaScript から DOM を直接操作するのは比較的コストが高い処理であり、 頻繁な DOM 更新はパフォーマンスの低下を引き起こします。
React は 仮想 DOM(Virtual DOM) という仕組みを採用しています。 仮想 DOM とは、実際の DOM を模したメモリ上の軽量な JavaScript オブジェクトです。 React は次のようなプロセスで効率的に画面を更新します。
- 状態(state)が変化する
- 新しい仮想 DOM ツリーが生成される
- 前回の仮想 DOM ツリーと新しいツリーの 差分(diff) を計算する
- 差分だけを実際の DOM に反映する
差分検出(Reconciliation)
この差分を計算して最小限の DOM 操作を行うプロセスを Reconciliation(リコンシリエーション) と呼びます。 React は以下の 2 つのヒューリスティック(経験則)を使うことで、O(n) の計算量で効率的に差分を検出しています。
- 異なるタイプの要素は異なるツリーを生成するとみなす
- 開発者が
key属性を使って、どの子要素が安定しているかヒントを与えられる
// 仮想 DOM は単なる JavaScript オブジェクト
const vdom = {
type: 'div',
props: {
className: 'container',
children: [
{ type: 'h1', props: { children: 'Hello' } },
{ type: 'p', props: { children: 'World' } }
]
}
};
仮想 DOM は React の実装上の詳細であり、開発者が直接操作するものではありません。 React 19 以降では内部の最適化がさらに進んでおり、開発者は仮想 DOM を意識せずに高速な UI を構築できます。
コンポーネント指向
React の UI は コンポーネント と呼ばれる独立した部品の組み合わせで構成されます。 コンポーネントは入力(props)を受け取り、画面に表示すべき React 要素を返す JavaScript 関数です。
// 小さなコンポーネントを組み合わせてページを構成する
function Header() {
return <header>サイトヘッダー</header>;
}
function Sidebar() {
return <aside>ナビゲーション</aside>;
}
function MainContent() {
return <main>本文コンテンツ</main>;
}
function App() {
return (
<div>
<Header />
<Sidebar />
<MainContent />
</div>
);
}
コンポーネント指向のメリットは次の通りです。
- 再利用性 — 同じコンポーネントを異なる場所やプロジェクトで再利用できる
- 保守性 — 各コンポーネントが独立しているため、変更の影響範囲が限定される
- テスト容易性 — コンポーネント単位でユニットテストが書ける
- 分業 — チーム内でコンポーネントごとに作業を分担しやすい
SPA とは
SPA(Single Page Application) とは、最初に 1 つの HTML ファイルを読み込み、 以降のページ遷移を JavaScript で制御するアプリケーションの形態です。 ページ遷移のたびにサーバーから新しい HTML を取得する従来の方式(MPA: Multi Page Application)とは異なり、 必要なデータだけを API 経由で取得して画面を動的に書き換えます。
| 項目 | SPA(React) | MPA(従来型) |
|---|---|---|
| 初回読み込み | やや遅い(JS バンドルの読み込み) | 速い(HTML のみ) |
| ページ遷移 | 高速(画面の部分更新) | 遅い(HTML 全体の再読み込み) |
| UX(操作感) | ネイティブアプリに近い滑らかさ | ページ遷移のたびに白い画面が挟まる |
| SEO | 追加の対策が必要(SSR / SSG) | サーバーが HTML を返すため有利 |
| サーバー負荷 | API のみ処理すればよい | 毎回 HTML を生成する必要がある |
React と従来の開発手法の比較
React と、jQuery や サーバーサイドテンプレート(JSP / Thymeleaf など)との比較を見てみましょう。
| 観点 | jQuery | サーバーサイドテンプレート (JSP / Thymeleaf) |
React |
|---|---|---|---|
| UI 更新方式 | 命令的に DOM を操作 | サーバーで HTML を生成 | 宣言的に仮想 DOM で差分更新 |
| 状態管理 | グローバル変数や DOM に埋め込み | サーバー側のセッション / モデル | コンポーネントの state |
| コンポーネント再利用 | プラグインで部分的に可能 | テンプレートのインクルード | コンポーネント単位で自然に再利用 |
| ページ遷移 | サーバーに HTML をリクエスト | サーバーに HTML をリクエスト | クライアント側でルーティング(SPA) |
| 学習コスト | 低い | サーバー言語の知識が必要 | 中程度(JSX、hooks 等) |
| 大規模開発 | コードが複雑になりやすい | サーバー負荷が増大 | コンポーネント分割で管理しやすい |
| エコシステム | 成熟しているが縮小傾向 | Java / Spring 等と密結合 | 非常に活発で拡大中 |
React を選ぶ理由
React のメリット
- 宣言的 UI により、状態と画面の対応が明確でバグが入りにくい
- コンポーネント指向で再利用性・保守性が高い
- 巨大なエコシステムと活発なコミュニティ
- React Native でモバイルアプリにも展開可能
- Meta が長期的にメンテナンスしており安定している
- TypeScript との相性が非常に良い
- 求人数が多く、スキルとしての市場価値が高い
React のデメリット
- HTML / CSS / JS の基礎知識に加え、JSX や Hooks の学習が必要
- SPA はSEO に弱い(SSR / SSG で対策可能だが複雑さが増す)
- 初回の JS バンドルサイズが大きくなりがち
- ライブラリ選定が多く、技術選択に迷いやすい(ルーティング、状態管理など)
- 頻繁なバージョンアップへの追随が必要
Tomcat との関係
このガイドでは、React アプリを Apache Tomcat で配信する構成を前提としています。 「React と Tomcat は何の関係があるのか?」と思われるかもしれませんが、仕組みはシンプルです。
React アプリの開発と本番は、以下のように 2 つのフェーズに分かれます。
| フェーズ | 使用するサーバー | 説明 |
|---|---|---|
| 開発時 | Vite 開発サーバー | npm run dev で起動。HMR(Hot Module Replacement)によりコード変更が即座にブラウザに反映される。 |
| 本番環境 | Apache Tomcat | npm run build で生成された静的ファイル(HTML / JS / CSS)を Tomcat の webapps に配置して配信。 |
React と Tomcat の関係を正しく理解しましょう。
React アプリをビルドすると、dist/ フォルダに純粋な HTML / JavaScript / CSS ファイルが出力されます。
Tomcat はこれらの静的ファイルをそのまま配信するだけで、サーバーサイドで React を実行しているわけではありません。
つまり Tomcat は「高機能な静的ファイルサーバー」として使われます。
ビルドと配信の流れをまとめると次の通りです。
# 1. プロジェクトをビルド
npm run build
# 2. dist/ フォルダが生成される
# dist/
# ├── index.html
# └── assets/
# ├── index-abc123.js
# └── index-def456.css
# 3. dist/ の中身を Tomcat の webapps にコピー
cp -r dist/* /opt/tomcat/webapps/my-app/
開発時には Vite の高速な開発サーバーで快適にコーディングし、 本番環境では既存の Tomcat インフラにそのまま載せられるのがこの構成のメリットです。 次の章では、実際に Node.js をインストールし、Vite で React プロジェクトを作成する手順を解説します。
既に Tomcat で Java のサーブレットや JSP を運用している環境でも、
React の静的ファイルを別のコンテキストパスに配置すれば共存できます。
例: /api/ は Java サーブレット、/app/ は React SPA。