Thymeleaf経験者のためのVue.js入門〜テンプレートエンジンからフロントエンドフレームワークへ〜

## 1. はじめに

Javaエンジニアにとって、**Thymeleaf**はSpring Bootと相性の良いテンプレートエンジンとして広く使われており、HTMLとJavaのデータをシームレスに統合できる点で非常に扱いやすい存在です。従来のWebアプリケーションでは、サーバーサイドでHTMLをレンダリングし、画面遷移のたびに再描画するスタイルが一般的でした。

しかし最近では、ユーザー体験の向上やインタラクティブなUI構築を求める声が高まり、フロントエンドの進化が急速に進んでいます。その中でも、**Vue.js**はシンプルな構文と学習コストの低さから、Javaエンジニアにも親しみやすいフロントエンドフレームワークとして注目を集めています。

この記事では、Thymeleafに慣れ親しんだエンジニアに向けて、Vue.jsとの違いを具体的に比較しながら紹介していきます。「HTMLテンプレート」としての似た側面から入りつつ、その背後にあるアーキテクチャの違いやレンダリング方式の違いを理解し、現代的なWebアプリ開発への第一歩を踏み出す手助けができれば幸いです。


## 2. ThymeleafとVue.jsの役割の違い

ThymeleafとVue.jsはどちらもHTMLテンプレートのように見えますが、**アプリケーションにおける役割と動作タイミングが根本的に異なります**。

### 2.1 Thymeleafの役割：サーバーサイドレンダリング

Thymeleafは、Spring BootなどのJavaアプリケーションと連携して動作する**サーバーサイドテンプレートエンジン**です。リクエストを受け取ったサーバー側でテンプレートをHTMLとして生成し、ブラウザに返却します。

- リクエストごとにHTMLをサーバーで構築
- Javaオブジェクトをテンプレートに埋め込める
- シンプルな画面構成に適しており、サーバー主導の処理に強み

```html
<!-- Thymeleafサンプル -->
<span th:text="${user.name}">ユーザー名</span>
```

### 2.2 Vue.jsの役割：クライアントサイドレンダリング

Vue.jsは、ブラウザ上で動作するクライアントサイドJavaScriptフレームワークです。HTMLテンプレートに似た構文を使いますが、実際にはJavaScriptでデータバインディングや動的描画が行われます。

- HTMLとJavaScriptの連携により、動的でインタラクティブなUIを実現
- 初期ロード後はAPI実行によってデータを取得し、画面に反映
- ユーザー操作への即時応答やSPA（Single Page Application）構築に適している

```vuejs
<!-- Vue.jsサンプル -->
<span>{{ user.name }}</span>
```

### 2.3 SPA（Single Page Application）とは？

SPAとは、「ページ全体を再読み込みせず、必要な部分だけを差し替えるWebアプリケーション」のことです。Vue.jsやReactなどのフレームワークは、このSPAを構築するための機能を持っています。

* 最初に1つのHTML（index.html）を読み込む
* 以降はJavaScriptで画面の差し替え・遷移を実現
* バックエンドとはJSONなどのAPI通信でやりとり
* ネイティブアプリのようなスムーズな操作感


Thymeleafを用いた従来のWebアプリケーション（いわゆるMPA：Multi-Page Application）では、画面遷移のたびにHTML全体を再取得する必要がありました。一方でSPAでは、ページ遷移のように見せながら実際には画面の一部だけを動的に差し替えることで、高速かつ直感的な操作を実現できます。



### 2.4 サーバー vs クライアントの役割まとめ

このように、Vue.jsは「テンプレートエンジン」ではなく、フロントエンドアプリケーションの基盤を担うフレームワークです。
|          | Thymeleaf                    | Vue.js                                       |
|--------------|------------------------------|----------------------------------------------|
| 実行場所     | サーバー                     | クライアント（ブラウザ）                     |
| 主な用途     | HTML生成                     | DOM操作・動的UI制御                         |
| データ取得   | Controller経由で直接渡す     | REST APIなどで非同期取得                    |
| ユースケース | 入力フォーム、一覧画面など   | インタラクティブな画面、SPA、UIコンポーネント制御 |


## 3. テンプレート構文の比較

ThymeleafとVue.jsはいずれも「HTMLベースのテンプレート構文」を採用しているため、初見では似ているように感じるかもしれません。しかし、実行タイミングや裏側の仕組みは大きく異なります。

以下に、よく使われる構文の対応関係をまとめます。

| 機能 | Thymeleaf | Vue.js | 説明 |
|------|-----------|--------|------|
| 変数展開 | `th:text="${user.name}"` | `{{ user.name }}` | Thymeleafはサーバー側でHTMLを生成、VueはJS変数をバインド |
| 条件分岐 | `th:if`, `th:unless` | `v-if`, `v-else`, `v-show` | DOMの表示/非表示制御 |
| 繰り返し | `th:each="item : ${list}"` | `v-for="item in list"` | リストの描画 |
| 属性バインディング | `th:href="@{/path}"` | `:href="'/path'"` | 動的属性設定（href, classなど） |
| イベント処理 | （サーバー経由） | `@click="doSomething"` | クライアントで直接制御 |
| フォームバインディング | `th:field="*{value}"` | `v-model="value"` | 入力値との双方向バインディング |

### 3.1 共通点と相違点のポイント

#### 共通点
- 両者ともHTMLに似た構文を使い、直感的に書ける
- データとテンプレートを結びつける「宣言的」なスタイル

#### 相違点
- **Thymeleaf**はサーバーでHTMLを生成して返すテンプレートエンジン
- **Vue.js**はブラウザ内でJavaScriptを通じてHTMLを動的に制御するフレームワーク
- Vueはデータの変化を監視し、**DOMを自動的に再描画（リアクティブ）**

### 3.2 用語解説：リアクティブ & 双方向データバインディングとは？

#### リアクティブ（Reactive）

Vue.jsのリアクティブとは、**変数の変化に応じてDOMが自動的に更新される**仕組みです。

```javascript
data() {
  return {
    message: 'こんにちは'
  };
}
// message を変更すると表示内容も即座に変わる
this.message = 'こんばんは';
```

#### 双方向データバインディング（Two-way Data Binding）
Vue.jsのv-modelを使うと、フォームの値とデータが相互に同期されます。

```html
<input v-model="userName" />
<p>こんにちは、{{ userName }} さん！</p>
```
- 入力が変われば変数が変わる
- 変数をプログラムで変えれば入力欄も更新される

Thymeleafはサーバー側でバインディングされる一方向構造のため、即時性やインタラクティブ性ではVueが圧倒的に強みを持つと言えます。

### 3.3 補足 v-ifとv-showの違い

#### v-showの基本構文
```vuejs
<div v-show="isVisible">この要素は表示状態に応じて切り替わります</div>
```

#### v-ifとの比較

| 比較項目 | v-show | v-if |
|--|--|--|
| DOMの扱い | DOMは常に生成されている | 条件に応じてDOM自体を追加/削除する |
| 表示/非表示 | display: none の切り替え | DOM自体を生成・破棄 |
| 初期レンダリング  | 常に行われる | 条件が true のときのみ |
| トグル頻度に適す | 頻繁な切り替えに向いている | 条件がまれに変わるときに適している |
| 使い分け | タブ切り替えやアコーディオンなど、頻繁に表示・非表示を切り替える要素 | 初期状態で表示されない or 条件により大きく表示有無が変わる要素 |



## 4. ページ読み込みの違い 〜サーバー再描画 vs クライアント差し替え〜

ThymeleafとVue.jsの間で、開発者が最も実感する違いの1つが「ページの読み込みと再描画の方法」です。

### 4.1 Thymeleaf：画面ごとにHTMLを再取得
Thymeleafを使った従来のWebアプリケーションでは、画面遷移のたびにサーバーからHTML全体を取得し、ブラウザがそれをレンダリングします。

- 各リクエストでサーバーがテンプレートをレンダリングし、HTMLを返す
- ブラウザはページ全体を再読み込み
- MPA（マルチページアプリケーション）型の構成

これは「マルチページアプリケーション（MPA）」と呼ばれる構造で、サーバー負荷や通信量が多く、UXにもやや遅延が発生しがちです。

### 4.2 Vue.js：ページ遷移してもDOMを差し替えるだけ
Vue.jsでは、最初のページロード時にindex.htmlを1回読み込んだ後、画面遷移や動的更新はすべてJavaScriptがDOMを差し替えて実現します。
- 初回ロード時にVueアプリを読み込み、以後はDOMだけを差し替え
- クライアント側でルーティングや描画を完結
- SPA（シングルページアプリケーション）型の構成

これは「シングルページアプリケーション（SPA）」と呼ばれ、UXの滑らかさとレスポンス速度に優れています。

### 4.3 MPAとSPAのページ遷移比較

|比較項目|MPA（Thymeleaf）|SPA（Vue.js）|
|--|--|--|
|ページ遷移時の通信|HTML全体を再取得|必要なデータ（JSON）のみ取得|
|再描画の範囲|ページ全体|必要なDOM部分だけ|
|通信量|多い（HTML全体を転送）|少ない（JSONのみ）|
|初回読み込み速度|比較的早い|JavaScript読み込みにやや時間|
|2回目以降の応答性|画面切替に時間がかかる|高速でスムーズ|
|サーバーの役割|HTMLを生成して返す|APIのみを提供（JSON）|
|クライアントの役割|基本的に表示のみ|表示+ロジック+状態管理|
|UX|ページ切替で白画面が出ることも|スムーズでリッチな操作感|
|状態管理|サーバーセッション依存|クライアントで細かく制御可能|


### 4.4 どちらを選ぶべきか？

- 入力フォームや帳票出力など静的画面が中心 → Thymeleaf
- フィルター・タブ・動的UIなど複雑な画面 → Vue.js

## 5. データバインディングの仕組み 〜状態とUIの同期の考え方〜
Webアプリケーションにおける「データの表示と更新」は、ユーザー体験や保守性に直結する重要な要素です。
ThymeleafとVue.jsでは、この **データバインディング（データとUIのつなぎ方）** の考え方が大きく異なります。

### 5.1 Thymeleafのデータバインディング
Thymeleafでは、Javaのオブジェクト（モデル）をテンプレートに渡して、HTMLを生成します。つまり、バインディングはリクエスト単位で行われ、静的なHTMLとして出力されるのが特徴です。

```html
<!-- サーバーで1回だけバインドされる -->
<input th:field="*{name}" />
```
- サーバーサイドでしかデータを変更できない
- 再バインディングには再リクエスト＋テンプレート再描画が必要
- 状態（model）とUI（HTML）は一時的に同期している

### 5.2 Vue.jsのデータバインディング
Vue.jsでは、JavaScriptオブジェクトとDOMが常にリアルタイムに同期されており、ユーザーの操作やプログラムの変更が即座に画面に反映されます。

```html
<!-- 入力と変数が自動で双方向バインディング -->
<input v-model="user.name" />
<p>{{ user.name }}さん、こんにちは！</p>
```
- ユーザー入力に応じてuser.nameが変わる
- user.nameが変われば表示も自動で変わる
- JavaScriptからの操作もリアルタイムにUIに反映される

### 5.3 単方向と双方向の違い

| バインディング方式 | 特徴 | Vue構文例 |
|-|-|-|
| 単方向 | 表示専用：データ → 画面のみ| {{ name }} や th:value="name" |
| 双方向 | 入力と状態が連動：データ ⇔ 画面 | v-model="name" |

### 5.4 状態とUIが一致するという考え方
Vue.jsでは「状態（State）がすべてのUIを支配する」という設計思想がベースにあります。
Thymeleafのように「表示だけテンプレートに渡す」方式とは異なり、状態がUIに反映され、UIの変化も状態に戻ることで、一貫性のあるアプリケーション設計が可能になります。

このようなデータバインディングの仕組みは、特にフォーム入力やダッシュボードのように「頻繁にデータが変わるUI」で威力を発揮します。

## 6. フォームとユーザー入力 〜テンプレートだけでは足りないUI制御〜
フォーム入力はWebアプリケーションにおいて最も頻繁に登場する機能のひとつです。ThymeleafとVue.jsでは、フォームの扱い方とデータ処理の考え方が大きく異なります。

### 6.1 Thymeleafでのフォーム
Thymeleafでは、Spring MVCの@ModelAttributeやフォームバッキングBeanと連携して、一度サーバーに送信してから処理するスタイルが主流です。

```html
<form th:action="@{/register}" method="post" th:object="${userForm}">
  <input type="text" th:field="*{name}" />
</form>
```
- th:fieldはフォームのname属性やvalue属性を自動生成
- 入力値はリクエストとしてサーバーに送信され、バリデーションと変換が行われる
- 再度レンダリングしてHTMLを返す必要がある

このように、ユーザー操作は都度サーバーとやり取りする必要があり、画面の再描画が発生するのが特徴です。

### 6.2 Vue.jsでのフォームとv-model
Vue.jsでは、v-modelディレクティブを使って、フォーム入力とデータが常にリアルタイムで結びついている状態を作れます。

```html
<form @submit.prevent="submit">
  <input type="text" v-model="user.name" />
  <button type="submit">登録</button>
</form>
```

- v-modelにより入力値とデータが常に同期
- ユーザー入力が即座にJavaScriptのデータとして反映される
- 入力内容に応じた即時バリデーションや表示制御も容易

```javascript
methods: {
  submit() {
    if (this.user.name.length < 1) {
      alert('名前は必須です');
    } else {
      // APIへPOST
    }
  }
}
```

### 6.3 サーバーバリデーション vs クライアント
|項目|サーバー|クライアント|
|--|--|--|
|バリデーションタイミング|サーバー側（Bean Validation）|クライアント側（JS）|
|入力補助|基本はHTMLの属性|自作ロジック・バリデーションライブラリが豊富|
|UX（エラーメッセージなど）|ページ遷移 or Ajax制御が必要|即時にフィードバック可能|


### 6.4 よくある実装の違い
| 項目 | Thymeleaf | Vue.js |
|--|--|--|
| 入力制御           | th:disabled, th:if など        | :disabled="条件", v-if など |
| 入力の即時チェック   | Javaバリデーション → 再描画 or JSロジック内で即時判定 | JSロジック内で即時判定 |
| 入力フォーム再利用 | fragment機能 | コンポーネント化（再利用しやすい） |

### 6.5 入力チェックはクライアント側？サーバー側？
フォーム入力チェックは、クライアント側とサーバー側の両方で行うのが基本方針です。それぞれの目的と役割は以下のように異なります。

#### クライアント側チェックの役割
- ユーザーへの即時フィードバックを提供し、操作ストレスを軽減する
- 入力ミスや漏れを早期に気づかせる（UXの向上）
- サーバーリクエストの無駄を減らす

#### サーバー側チェックの役割
- 最終的な正当性の保証（不正入力やバイパスを防ぐ）
- フロントエンドが改変されても安全性を保つ
- セキュリティ対策（クロスサイトスクリプティング、SQLインジェクション対策）

#### 一般的な推奨パターン

|チェック項目|実行場所|備考|
|--|--|--|
|空欄チェック・文字数制限|両方|即時性重視・UX向上|
|日付妥当性・選択肢整合性|両方|クライアント補助＋サーバー再検証|
|認証・認可・データ整合性|サーバー|改ざん想定し必須|
|重複チェック（メール等）|サーバー（API）|API対応あればクライアント実施可|

Vue.jsはクライアント側のチェックに非常に適していますが、それだけに頼るのではなく、サーバー側のチェックも必ず併用することが重要です。
「フロントはユーザーの利便性、サーバーはシステムの堅牢性」を担保する、という役割分担が基本的な考え方です。

## 7. 状態管理とルーティング 〜SPAを支える基盤技術〜
Vue.jsを使ってアプリケーションを構築する際、複数の画面を持つSPA（Single Page Application）を意識した設計が求められるようになります。その際に重要となるのが、状態管理とルーティングの考え方です。
### 7.1 Thymeleafにおける状態とルーティング
Thymeleafを使う場合、画面遷移はURLに対するサーバーリクエストとレスポンスの繰り返しによって実現されます。
- 各URLに対してControllerが対応し、ModelとテンプレートでHTMLを生成
- 状態（セッションなど）はサーバーサイドで保持
- リクエストのたびに状態が更新され、画面も再描画される

このように、 **画面** ＝ **URL** ＝ **テンプレート** がほぼ1対1で対応し、状態管理の中心もサーバー側にあります。

### 7.2 Vue.jsにおける状態管理（Vuex/Pinia + 認可API対応）
Vue.jsでは、ユーザーが画面を操作するたびに状態（データ）が変化し、それに応じてUIが変わります。これを一貫して管理するために導入されるのが状態管理ライブラリです。

#### 主な状態管理ツール
- Vuex：Vue公式の状態管理ライブラリ（Vue2〜3で広く使われた）
- Pinia：Vue3以降の推奨ライブラリ。軽量・直感的でComposition APIと親和性が高い

#### 管理する状態の例
- ログイン中のユーザー情報
- 選択中の商品・カート情報
- フィルター条件や一覧の並び順
- 通信中フラグ（loading）など

上記の状態を一元管理することで、

- 複数のコンポーネント間での状態共有
- 特定のタイミングで状態を初期化・更新
- 状態変化に応じた自動UI更新

といったことが可能になります。

#### 認可API（セッションIDベース）との連携
SPAにおいても、セキュリティを担保するためにセッションIDを用いた認可API設計は一般的です。
この場合、以下のような構成でVueアプリとサーバーAPIが連携します

```mermaid
sequenceDiagram
  participant ブラウザ
  participant VueApp
  participant API
  participant SessionStore

  ブラウザ->>VueApp: ログイン画面表示
  VueApp->>API: POST /login（認証）
  API->>SessionStore: セッション生成
  API-->>ブラウザ: Set-Cookie: JSESSIONID=xxx
  VueApp->>API: 認可付きAPIリクエスト
  API->>SessionStore: セッション確認→許可
```
1. ログイン後、セッションIDはCookieに保存（HttpOnly推奨）
2. 以降のAPI通信は自動的にセッション付きで送信される（CORS設定に注意）
3. 認証済みユーザーの情報（氏名、権限など）を取得し、Vue側で状態として保持
4. 必要に応じてVuex/PiniaのStoreに格納

:::note info
状態は保持するが、信頼はサーバーで確認
:::
VueのStoreにユーザー情報を保持することは表示制御やUIロジックに有用ですが、
本質的な認可（アクセス制御）はサーバー側で必ず行う必要があります。
クライアント側の状態は改ざん可能であることを常に意識することが大切。

**表示していいか？** はクライアント、 **実行していいか？** はサーバーで判定

このように、セッションIDベースの認可APIを前提とした状態管理では、
- Vueアプリは状態をローカルに持ちつつ
- サーバーAPI側でセッションを検証して認可を担保 という 責務分離が重要です。

### 7.3 Vue Routerによるルーティング
- vue-routerでURLとコンポーネントを紐づけ
- router-viewで画面差し替え
- router-linkで遷移

```javascript
const routes = [
  { path: '/register', component: RegisterPage }
];
```

### 7.4 状態とルーティングの組み合わせでSPAが成立
| 比較項目     | Thymeleaf                     | Vue.js（SPA）                         |
|--------------|-------------------------------|----------------------------------------|
| 状態保持     | セッション/Model              | Pinia/Vuex（クライアント側）           |
| 画面遷移     | テンプレート単位で切り替え     | コンポーネント切り替え                |
| 認証管理     | Java側のFilterやInterceptor   | APIレイヤーでトークン確認など         |

## 8. 実装スタイルの違いと開発体験 〜テンプレートからUIアーキテクチャへ〜
ThymeleafとVue.jsは「HTMLに似た構文で画面を作る」という点では共通していますが、開発スタイルや考え方は大きく異なります。この章では、両者の実装アプローチと開発体験（DX: Developer Experience）を比較します。

### 8.1 Thymeleafの実装スタイル

ThymeleafはJava側（Spring Boot）からテンプレートにデータを渡し、HTMLをレンダリングする形で画面を構成します。
- テンプレート中心の構成：画面は .html テンプレートファイルごとに分かれる
- バックエンド主導：Controller から Model にデータを入れてテンプレートへ
- 開発体験
    - Java開発者にとって親和性が高い
    - デバッグしやすく、テンプレートがシンプル
    - 単一ファイルで完結しやすい反面、UIの再利用や状態変化への対応は難しい

### 8.2 Vue.jsの実装スタイル
Vue.jsはコンポーネントベースの開発スタイルを採用しており、画面を機能単位で分割しながら開発します。

```vue
<!-- UserCard.vue -->
<template>
  <div class="card">
    <p>{{ user.name }}</p>
  </div>
</template>

<script>
export default {
  props: ['user']
}
</script>
```

- UIを部品として切り出すコンポーネント設計
- 状態・テンプレート・ロジックが1ファイルにまとまる（SFC: Single File Component）
- 状態変更やAPI連携をJavaScript側で柔軟に実装可能
- 再利用性が高く、大規模開発にも強い

### 8.3 開発体験（DX）の違い
|観点|Thymeleaf|Vue.js|
|--|--|--|
|コーディング対象|HTMLテンプレート+Java|JavaScript（またはTypeScript）|
|テンプレート構造|画面単位でシンプル|コンポーネント単位で再利用前提|
|データ結びつき|ControllerのModel依存|状態管理+API依存|
|リアルタイム性|なし（都度リクエスト）|高（即時反映UI）|
|開発効率|小規模なら良|UI変化多いなら優位|
|テストしやすさ|Controller・Service向き|コンポーネント単位（Jest等）|

### 8.4 開発ツール
#### Thymeleaf開発
- Spring Boot DevTools によるホットリロード
- サーバーの再起動が必要な場合もあり

#### Vue開発
- vite や webpack を使った開発サーバで即時反映
- ChromeのVue DevTools で状態・イベントの確認が可能
- ESLintやPrettierなどの自動フォーマッタとも高相性

Thymeleafは「テンプレートとしてのシンプルさ」に強みがありますが、Vueは「アプリケーションの構成・分離・再利用」に長けており、画面の複雑化や拡張性を見据えた開発には特に有利です。

### 8.5 ファイル構成の比較（ユーザー登録画面）
#### ThymeleafベースのSpring Boot構成例（MPA）
```
myapp/
├── src/
│   ├── main/
│   │   ├── java/com/example/myapp/
│   │   │   ├── controller/
│   │   │   │   └── UserController.java
│   │   │   ├── model/
│   │   │   │   └── User.java
│   │   │   └── service/
│   │   │       └── UserService.java
│   │   └── resources/
│   │       ├── templates/
│   │       │   └── user/
│   │       │       └── register.html
│   │       └── application.properties
```
- 画面は register.html に1つ
- ロジックはController〜Service〜Modelの三層構成
- データバインドはサーバー側（Spring MVC）

#### Vue.js構成例（SPA）
```
my-vue-app/
├── src/
│   ├── components/
│   │   └── UserForm.vue
│   ├── pages/
│   │   └── RegisterPage.vue
│   ├── stores/
│   │   └── userStore.js  （← Pinia や Vuex）
│   ├── router/
│   │   └── index.js
│   ├── App.vue
│   └── main.js
├── public/
│   └── index.html
├── vite.config.js
├── package.json
```
- 画面は RegisterPage.vue に相当（ルーティング対象）
- フォーム部品は UserForm.vue に切り出し（再利用可）
- 状態管理は userStore.js に集約
- サーバーAPIとの通信はJSで行う（例：axios）

#### 比較まとめ
|比較項目|Thymeleaf構成|Vue.js構成|
|--|--|--|
|画面単位|テンプレートHTML単位|コンポーネント+ルーティング|
|UI分離|基本なし（1ファイル完結）|components/に分割|
|状態管理|Controller+Modelで保持|Store（Vuex/Pinia）で一元管理|
|ビルド方式|Javaビルド（Gradle/Maven）|Node.jsベース（Vite/Webpack）|
|ロジック実装|Java（Controller,Service）|JavaScript（methods,setup）|

このように、Thymeleafはテンプレート中心、VueはUI部品・状態・遷移を分けて構築する構成になっているのが特徴です。
どちらが適しているかはアプリケーションの規模・動的性・再利用性によって選択するのが望ましいです。

## 9. Vue.jsを導入するためのステップ  〜Thymeleafとの共存から完全SPAへの道〜

Vue.jsを既存のSpring Boot + Thymeleafプロジェクトに導入するには、段階的に進める方法と完全に分離する方法の2つがあります。どちらを選ぶかは、チーム体制や開発対象の性質に応じて検討する必要があります。

### 9.1 導入パターン

#### パターン①：既存Thymeleafと共存（部分的にVueを導入）
```html
<!-- register.html（Thymeleafテンプレート） -->
<div id="app">
  <user-form></user-form>
</div>

<script src="/js/vue.global.js"></script>
<script src="/js/userFormComponent.js"></script>
```

- 既存テンプレートにVueコンポーネントをインラインで埋め込む
- ボタン操作・リスト表示・バリデーションなど一部だけをVueで担当
- 段階的に置き換えていくことが可能
- Spring Bootプロジェクトの構成を大きく変えずに導入できる

**向いているケース**
- 徐々にVueに慣れたい
- リッチなUIを一部だけ使いたい
- 画面遷移はこれまで通りサーバー側で

#### パターン②：Vueアプリを完全に分離してSPA構成に
```
frontend/   ← Vueアプリ（SPA）
backend/    ← Spring Boot APIサーバー
```
- フロントエンドはVue CLIやViteで完全独立構成に
- Spring BootはREST API提供に専念（JSON通信）
- CORS設定を行い、ポートをまたいで通信
- フロントエンドとバックエンドで明確な責務分離が実現

**向いているケース**
- 大規模な管理画面・フロント重視の開発
- 複数人で並行開発するチーム体制
- スマホアプリとAPIを共通化するなど、API中心設計を目指す場合

### 9.2 段階的移行の実例（実務でよくある構成）

1. 画面内の動的部分だけVueで制御（例：入力補助、動的リスト）
1. 複雑な一覧画面や検索フォームをVueに置き換え
1. 状態管理やルーティングを導入してVueアプリに拡張
1. 最終的にThymeleafの役割はレイアウト提供のみに

このように、0か100かではなく、徐々にVueへ寄せていく選択肢も現実的です。

### 9.3 Spring BootとVueを組み合わせる際の技術要素

|技術要素|概要|
|--|--|
|CORS設定|Vue→Spring API許可設定（WebMvcConfigurer等）|
|認証/認可|Cookie+セッション or JWT（用途に応じて）|
|REST API設計|Vue向けにJSON返すControllerを分離|
|ビルド・デプロイ|Vueビルド成果物をSpringの/staticに配置も可|
|CI/CD構成|フロント・バックのビルド分離or統合|

Vue.jsの導入は、ユーザー体験の向上や保守性の高いフロントエンド構築に非常に有効です。
Thymeleafとの違いを理解した上で、自チームに合ったスケールと段階で導入していくのが成功の鍵となります。

## 10. おわりに  〜テンプレートエンジンからフロントエンドフレームワークへ〜
ThymeleafとVue.jsは、どちらも「HTMLをベースに画面を構築する」という共通点を持ちながら、設計思想・責務・動作のタイミングがまったく異なる技術です。

ThymeleafはJavaエンジニアにとって扱いやすく、サーバー主導で安定した画面を提供できる一方で、Vue.jsはクライアント主導でリッチなインタラクティブUIを可能にします。
特に近年では、ユーザーの操作感を重視したUIが求められるケースが増え、Vue.jsのようなモダンなフロントエンド技術の重要性が高まっています。

### こんなときはVue.jsを検討しよう
- ユーザー操作が多く、即時応答が求められる
- 複数の状態（タブ・フィルター・ページングなど）を画面上で切り替えたい
- 同じ部品（例：フォームやリスト）を複数箇所で再利用したい
- フロントとバックエンドを明確に分離し、並行開発したい

逆に、静的で変化の少ない入力画面や帳票出力のような要件であれば、Thymeleafのままでも十分なケースもあります。

### 技術の選択は目的に応じて
Vue.jsが優れているからといって、すべてをSPAにすべきというわけではありません。
重要なのは、自分たちのプロジェクトや組織にとって適した技術を選び、効果的に活用することです。

本記事が、Thymeleafに慣れたエンジニアがVue.jsを正しく理解し、導入への第一歩を踏み出す助けになれば幸いです。