開発・技術選定

Next.js が本格的な選択肢になった — Django と組み合わせるときの構成

以前は「SEO が必要なら SPA は避ける」が定石でしたが、
Next.js の SSR/SSG が実用段階に入り、その前提が変わりました。
Django と組み合わせるときの構成を整理します。

役割分担

Next.js  … 画面の描画(SSR/SSG/CSR を画面ごとに選ぶ)
Django   … API、認証、権限、業務ロジック、管理画面

Django の管理画面をそのまま残せるのがこの構成の実利です。
運用者向けの画面を作り直さずに済みます。

画面ごとに描画方法を選ぶ

Next.js の利点は「全部 SSR」ではなく、画面ごとに選べることです。

画面 方式 理由
LP・記事 SSG 更新頻度が低い。最速で配信できる
商品一覧 SSR 在庫が変わる。SEO も要る
マイページ CSR ログイン必須。SEO 不要

ここを一律にすると、どこかで必ず無理が出ます。

認証をどう持つか

分離構成で最も設計が割れるのがここです。実際の判断はこうしています。

同一ドメインで運用できるなら、Cookie セッションのまま

example.com        → Next.js
example.com/api/   → Django(リバースプロキシで振り分け)

Django のセッション Cookie がそのまま使えます。
HttpOnly + Secure + SameSite=Lax にしておけば、
トークンを JavaScript から触らせずに済むので、XSS 時の被害が小さくなります。

ドメインが分かれるなら、トークン + リフレッシュ

その場合も、アクセストークンを localStorage に置くのは避けます。
XSS があった瞬間に持ち出されます。可能なら Cookie に寄せます。

CORS と CSRF

同一ドメイン構成にすると CORS の設定自体が不要になります。
これも同一ドメインを勧める理由です。

分離する場合は Django 側で明示的に許可します。

CORS_ALLOWED_ORIGINS = ["https://app.example.com"]
CORS_ALLOW_CREDENTIALS = True
CSRF_TRUSTED_ORIGINS = ["https://app.example.com"]

CORS_ALLOW_ALL_ORIGINS = True は本番では使いません。

ISR を使うときの注意

更新のあった記事だけ再生成する仕組みは強力ですが、
再生成の失敗に気づけない構成になりがちです。
Django 側で更新イベントを記録し、再生成の成否をログに残すようにしています。

この構成を選ばない場合

  • 画面数が少ない業務システム
  • 納品後に社内の非エンジニアが触る
  • 更新が年に数回

この場合は Django だけで完結させたほうが、総コストが確実に低くなります。

まとめ

  • 画面ごとに SSG / SSR / CSR を選べることが最大の利点
  • 可能なら同一ドメインにして Cookie セッションを使い回す(CORS も不要になる)
  • トークンを localStorage に置かない
  • 小規模・低更新頻度なら分離しないほうが安い