Spring Boot経験者向け：Next.js入門ガイド

## はじめに

Spring BootはJavaエコシステムでのWeb開発を効率化するフレームワークで、Controller・Service・Repositoryという明確なレイヤー分割やDI、Thymeleafによるサーバーサイドレンダリング(SSR)など、オーソドックスなバックエンド構築手法が確立されています。

一方、フロントエンド界隈では、Reactとその上で動くNext.jsが主流になりつつあります。Next.jsは「Reactベースのフロントエンドフレームワーク」でありながら、SSRやSSG(静的サイト生成)、API Routesといった仕組みを内包し、**フロントとバックをシームレスにつなげる**機能を提供します。

本記事では、Spring Bootでの開発経験がある方を対象に、Next.js（特にNext.js 13以降推奨のApp Router構成）を理解するためのヒントをまとめます。加えて、実運用を意識したSplunkへのログ送信やエラーコード設計の比較も紹介します。


## Spring MVC & ThymeleafとNext.js & Reactの対比

### 基本的な対応関係

- **Spring MVC & Thymeleaf**
  - Controller (`@Controller`): HTTPリクエストを受け、Serviceからデータ取得し、ModelをViewへ渡す
  - View(Thymeleaf/JSP): モデルデータをもとにHTML生成（SSR）
  - RestController (`@RestController`): JSONレスポンスのAPIを提供

- **Next.js & React**
  - サーバーコンポーネント (`app/page.tsx`など): リクエスト時にサーバー側で実行、`fetch()`でデータ取得しSSR
  - Reactコンポーネント: HTML生成ロジックをJSXで記述（テンプレートエンジン相当）
  - API Routes (`app/api/.../route.ts`): 簡易なAPIエンドポイントを提供（JSONレスポンス）

SpringでController+ThymeleafでSSRしていた部分は、Next.jsでは「サーバーコンポーネント＋Reactコンポーネント」に置き換わります。また、Springで`@RestController`でJSONを返していたような処理は、Next.jsでは`app/api`配下にファイルを設置し、`GET()`関数を記述するだけで実現可能です。

### 具体例

#### Spring側

```java
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public String getUsers(Model model) {
        List<User> users = userService.getAllUsers();
        model.addAttribute("users", users);
        return "users"; // Thymeleafテンプレート(users.html)へ
    }
}
```

```html
<!-- users.html (Thymeleaf) -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>User List</title></head>
<body>
<h1>User List</h1>
<ul>
  <li th:each="user : ${users}" th:text="${user.name}"></li>
</ul>
</body>
</html>
```

#### Next.js側(App Router)
```typescript
// app/users/page.tsx
type User = { id: number; name: string };

export default async function UsersPage() {
  const res = await fetch('http://localhost:3000/api/users', { cache: 'no-store' });
  const users: User[] = await res.json();

  return (
    <div>
      <h1>User List (SSR)</h1>
      <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
    </div>
  );
}
```

## APIルートとService層の関係
SpringではController・Service・Repositoryのレイヤリングが定番です。一方、Next.jsではAPI Routes内に直接DBアクセスやロジックを記述することもできます。

大規模になればlib/ディレクトリにService相当の関数を分離し、API Routeから呼ぶなど、Spring的なアーキテクチャパターンを任意で適用可能です。

## SSRとSSG
Spring + Thymeleafは基本SSRですが、Next.jsではSSRに加えてSSG (Static Site Generation) も可能です。ビルド時に静的HTMLを生成し、CDNから高速配信するなど、パフォーマンス向上やスケーラビリティ確保が容易です。

- SSR: リクエストごとにサーバーでHTML生成 (cache: 'no-store'など)
- SSG: ビルド時または初回アクセス時にHTML生成、その後は静的ファイル配信 (cache: 'force-cache'、generateStaticParams()など)

## Splunk等へのログ出し
### Spring Bootでのロギング
- Logback + SLF4Jが定番
- logback-spring.xmlでJSON出力設定
- サーバー側でSplunk Universal Forwarderがログファイルを監視してSplunkへ送信
### Next.jsでのロギング
Node.js用のロガー（winston, pino）を使用
JSON形式で標準出力へログを出力
コンテナ環境などでFluentdやSplunk Forwarder経由でSplunkへ送信可能
```typescript
// Next.js API Route例 (winston使用)
import { NextResponse } from 'next/server';
import { createLogger, format, transports } from 'winston';

const logger = createLogger({
  level: 'info',
  format: format.json(),
  transports: [new transports.Console()]
});

export async function GET() {
  logger.info({ event: 'fetch_users', message: 'Fetching user data' });
  const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
  return NextResponse.json(users);
}
```

## エラーコード設計
### Spring Bootのエラー処理
- @ControllerAdvice + @ExceptionHandlerで一元的なエラーハンドリング
- ErrorResponse DTOを定義し、codeやmessageで統一したフォーマット返却

```java
@ControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(UserNotFoundException.class)
  public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
    ErrorResponse error = new ErrorResponse("USER_NOT_FOUND", "User does not exist");
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
  }
}
```
### Next.jsのエラー処理

- API Route内でtry-catchを使用し、NextResponse.json()で柔軟にエラーJSONを返却
- 共通的なエラー処理はユーティリティ関数やmiddleware.tsでカスタム
- error.tsxを用いてルート単位のエラーページ表示も可能

```typescript
export async function GET() {
  try {
    throw new Error('User not found');
  } catch (err: any) {
    return NextResponse.json(
      { code: 'USER_NOT_FOUND', message: err.message },
      { status: 404 }
    );
  }
}
```

# まとめ
- Spring MVC & Thymeleaf → Next.js & React：
SSRを実現する思想は似ており、Controller+Viewをサーバーコンポーネント+Reactで代替。

- API・Service設計：
SpringではControllerとServiceが明確だが、Next.jsは自由度が高く、必要に応じて分割可能。

- SSR/SSG/ISR：
Next.jsはビルド時静的生成(SSG)や増分的再生成(ISR)でパフォーマンス向上が容易。

- ログとSplunk：
SpringはLogback、Next.jsはNodeロガーを利用、最終的にJSON出力してSplunk送信というパターンは共通。

- エラーコード設計：
Springの@ExceptionHandlerほど標準化はないが、NextResponseで自由にJSONエラーを返せるため、Springで慣れたエラーポリシーを容易に再現可能。

Spring Boot経験者にとって、Next.jsはフロントとバックの境界をシームレスに扱えるフルスタックフレームワークです。
Spring的なアーキテクチャパターンを下敷きに、Next.js特有のSSR/SSGやAPI Routesを活用することで、柔軟でスケーラブルなWebアプリ開発を進めることができます。