SPA・SSR・SSG — レンダリング方式の選び方
CursorやClaude Codeでコードを生成していると、あるタイミングで必ずこんな悩みが出てきます。
「use clientってどこに付ければいいの?」
付けすぎると怒られたような気がするし、付けなさすぎると動かない。Claude Code に聞くたびに付けたり外したりして、何が正解かわからなくなってしまう。
これはバイブコーダーあるあるです。そして、この悩みの根本にあるのが「レンダリング方式の違い」を理解していないことです。
今回は、Webアプリがどうやって画面を表示するのかという仕組みを、4つの方式に分けて解説します。これを知ると、use clientの謎が一気に解けます。
そもそも「レンダリング」とは何か
レンダリングとは、データやコードを元にして、ブラウザが表示できる形のHTMLを作り出す処理のことです。
料理に例えると、材料(データ)をレシピ(コード)に従って調理して、完成品(HTML)を皿に盛り付ける工程です。
問題は「どこで調理するか」です。あなたのパソコン(ブラウザ)で調理するのか、サーバー(料理人のいるキッチン)で調理して完成品を届けるのかで、体験と速さが大きく変わります。
この「どこで調理するか」の違いが、4つのレンダリング方式を生み出しています。
4つのレンダリング方式
CSR(クライアントサイドレンダリング)
CSRとは、ブラウザ(クライアント)側でHTMLを生成する方式のことです。SPAとも呼ばれます。
SPAとはシングルページアプリケーションの略で、最初に1枚のHTMLとJavaScriptをまるごとダウンロードして、以降はページ遷移のたびにJavaScriptが画面を書き換えていく仕組みです。
動き方を順番で見てみましょう。
- ブラウザがサーバーにアクセスする
- サーバーはほぼ空のHTMLとJavaScriptを返す
- ブラウザがJavaScriptを実行し始める
- JavaScriptがAPIを呼んでデータを取得する
- データが揃ってから画面が表示される
メリットは、一度読み込んだ後のページ切り替えが速く、スマホアプリのようななめらかな体験を作れることです。
デメリットは、最初の表示が遅いことと、検索エンジン(SEO)に弱いことです。Googleのクローラーは最初のHTMLを見てサイトの内容を判断しますが、CSRでは最初のHTMLがほぼ空なので、内容を正しく読んでもらえないことがあります。
向いているサービス:管理画面、ダッシュボード、チャットアプリ、外部に公開しない社内ツール。SEOが不要で、ログインしてから使うものに向いています。
SSR(サーバーサイドレンダリング)
SSRとは、ユーザーがページを開いたタイミングでサーバー側がHTMLを生成して返す方式のことです。
動き方を順番で見てみましょう。
- ブラウザがサーバーにアクセスする
- サーバーがその場でHTMLを生成する(データベースから情報を取得するなど)
- 完成したHTMLをブラウザに返す
- ブラウザはHTMLを受け取ってすぐに表示できる
メリットは、最初から中身が詰まったHTMLが届くので表示が速く、SEOにも強いことです。
デメリットは、アクセスのたびにサーバーで処理が走るので、サーバーへの負荷が高くなることです。アクセスが集中すると応答が遅くなる場合があります。
向いているサービス:ECサイト、ニュースサイト、予約サービス。「ユーザーごとに見せる内容が違う」「最新データを必ず表示する必要がある」場合に向いています。
SSG(静的サイト生成)
SSGとは、サイトをビルドする(公開準備をする)タイミングであらかじめすべてのHTMLを生成しておき、アクセスのたびに作り済みのHTMLをそのまま返す方式のことです。
動き方を順番で見てみましょう。
- デプロイ時にすべてのページのHTMLを事前に生成する
- ブラウザがアクセスする
- 作り済みのHTMLをそのまま返す(サーバーで処理なし)
- ブラウザがすぐに表示できる
メリットは、静的なファイルを返すだけなのでとにかく速く、サーバー負荷もほぼゼロです。CDN(世界中に分散したサーバー群)に乗せれば、どこからアクセスしても爆速で表示されます。
デメリットは、内容を更新するたびに再ビルドが必要なことです。リアルタイムで変わるデータには向きません。
向いているサービス:ブログ、企業サイト、ドキュメントサイト、ランディングページ。更新頻度が低く、全ユーザーに同じ内容を見せるものに最適です。
ISR(増分静的再生成)
ISRとは、SSGの欠点を補った方式で、一定時間が経過したらバックグラウンドでページを自動的に再生成する仕組みのことです。
SSGは「ビルド時に全ページを作る」でしたが、ISRは「最初はSSGと同じ。でも指定した時間が過ぎたら、次にアクセスがあった時に裏でこっそり再生成する」という動き方をします。
例えば「60秒ごとに更新」と設定すると、1分以内に何万人がアクセスしても全員に同じキャッシュ済みHTMLを返し、1分経過後は次のアクセスのタイミングで裏側でページを更新します。
向いているサービス:ブログ(更新があっても数分の遅延でOK)、商品ページ(価格や在庫がリアルタイムでなくてよい場合)、ランキングページ。SSGの速さとある程度の鮮度を両立したい場面に向いています。
一目でわかる比較表
ここまでの4方式を整理します。
HTMLの生成タイミングを軸に見ると次のようになります。
CSRはブラウザ上でリアルタイムに生成します。SSRはサーバー上でリクエストのたびに生成します。SSGはビルド時に事前生成します。ISRはビルド時に事前生成し、一定時間後に自動更新します。
速さの観点では、SSGとISRが最速です。サーバーで処理が走らず、CDNから直接ファイルを返すだけだからです。SSRはアクセスのたびにサーバー処理が入るため少し遅くなります。CSRは初回ロードが最も遅くなりがちです。
SEOの強さでは、SSRとSSGが有利です。最初から内容の詰まったHTMLが届くので、Googleのクローラーがちゃんと読んでくれます。CSRは最初のHTMLが空なので不利になることがあります(最近は改善されてきていますが)。
「use client はどこに付けるか」問題の正体
ここで冒頭の悩みに戻ります。
Next.js 13以降(App Router)では、コンポーネントはデフォルトで「サーバーコンポーネント」になっています。サーバーコンポーネントとは、サーバー側で実行されるコンポーネントのことで、データの取得やHTMLの生成はサーバーで行い、ブラウザには完成したHTMLが届きます。
一方、ボタンのクリックやフォームへの入力など、ユーザーの操作に反応する処理はブラウザ側でしか動きません。そこで「このコンポーネントはブラウザ側でも動かす必要がある」と宣言するのが "use client" です。
つまり、"use client" を付けるべき場面は次のとおりです。
useStateやuseEffectなどのReactフックを使う場合onClickなどのイベントハンドラを使う場合- ブラウザのAPI(
window,localStorageなど)を使う場合 - アニメーションやリアルタイムで変化するUIを作る場合
逆に、"use client" が不要な場面はこちらです。
- データベースからデータを取得するだけの処理
- 静的なHTMLを組み立てるだけのコンポーネント
- API Routeの処理
バイブコーダーがよくやってしまうのは、「エラーが出たからとりあえず "use client" を付ける」という対症療法です。これは一時的に解決するように見えますが、本来サーバーで動くべき処理をブラウザに持ってきてしまうので、パフォーマンスが落ちたり、サーバー専用の機能(秘密のAPIキーへのアクセスなど)が使えなくなったりします。
サービスの種類ごとの選び方
実際にどの方式を選べばよいか、サービスの種類ごとに整理します。
ブログ・企業サイト・ランディングページ → SSG
内容が頻繁に変わらず、全ユーザーに同じページを見せるサービスはSSGが最適です。
ビルド時に全ページのHTMLを作り終えるので、アクセスが来てもサーバーで処理することが何もありません。Vercelのようなホスティングサービスと組み合わせると、世界中どこからアクセスしても爆速で表示されます。
Next.jsでは、データを返す関数を async のサーバーコンポーネントに書くだけで、自動的にSSGになります。何も設定しなくていいので、実はNext.jsで最も「手間がかからない」方式です。
ECサイト・予約サービス → SSR(またはISR)
「ユーザーAには会員価格、ユーザーBには通常価格」のようにユーザーによって見せる内容が変わるサービスや、在庫状況をリアルタイムで反映させたいECサイトはSSRが向いています。
ただし商品ページのように「数分程度の遅延は許容できる」ならISRでも十分です。ISRにするとサーバー負荷が大幅に下がり、速度も上がります。
管理画面・ダッシュボード・チャット → CSR
ログインが必要なサービス、SEOが不要なサービス、スマホアプリのような体験を重視するサービスはCSRが向いています。
Next.jsでCSRにするには、コンポーネントに "use client" を付けて、useEffect の中でデータを取得します。または、Next.jsのPage Routerを使う方法もあります。
ただし「管理画面だから全部CSR」ではなく、管理画面の中でも「一覧ページはSSR(常に最新データ)」「グラフはCSR(インタラクティブ)」のように混在させることができます。
コンテンツが多いブログ・ドキュメント → ISR
記事が毎日追加されるブログや、頻繁に更新されるドキュメントサービスにはISRが向いています。
SSGでは、記事が1000本あればビルドに時間がかかります。ISRなら「最初のアクセスがあったとき生成」「1時間後に更新」のような設定ができるので、ビルド時間を短縮しながら常にそれなりに新鮮なコンテンツを届けられます。
Next.jsでの実装イメージ
実際にコードがどう変わるか、雰囲気だけ見ておきましょう。Claude Code に指示するときのヒントになります。
SSGの場合、サーバーコンポーネントでデータを取得するだけです。
// デフォルトはSSG(何もしなくていい)
export default async function BlogPage() {
const posts = await fetchPosts() // ビルド時に実行される
return <PostList posts={posts} />
}
SSRの場合、fetchの呼び出しに cache: 'no-store' を付けます。
// SSR: リクエストのたびにデータを取得
export default async function ProductPage() {
const product = await fetch('/api/product', { cache: 'no-store' })
return <ProductDetail product={product} />
}
ISRの場合は、revalidate を秒数で指定します。
// ISR: 60秒ごとに再生成
export const revalidate = 60
export default async function ArticlePage() {
const article = await fetchArticle()
return <Article data={article} />
}
CSRの場合は、"use client" を付けて useEffect でデータを取得します。
"use client"
import { useEffect, useState } from 'react'
export default function Dashboard() {
const [data, setData] = useState(null)
useEffect(() => {
fetch('/api/dashboard').then(r => r.json()).then(setData)
}, [])
return <DashboardView data={data} />
}
このコードを全部覚える必要はありません。Claude Code に「このページはSSRにして」「ダッシュボードなのでCSRで実装して」と伝えるだけで、適切なコードを生成してくれます。
「use client を付けすぎた」ときの直し方
Claudeに言われるがまま "use client" を付けまくってしまった場合の対処法を説明します。
まず、"use client" が付いているコンポーネントを全部洗い出します。そして一つひとつ確認します。「このコンポーネントに useState や useEffect や onClick があるか?」という問いに対してNoなら、"use client" を外してみましょう。
エラーが出なければ外してOKです。エラーが出たら、「なぜエラーが出るか」を Claude に聞いてみましょう。「このコンポーネントから "use client" を外したらエラーになった。原因と解決策を教えて」と伝えると、適切に説明してくれます。
また、"use client" はツリー(コンポーネントの親子関係)を通じて下に伝播します。つまり、親コンポーネントに "use client" が付いていると、その子孫コンポーネントは全部クライアントコンポーネントとして扱われます。
そのため、"use client" をできるだけ「葉っぱ」(ツリーの末端)に近いコンポーネントだけに付けるのが理想です。ボタンひとつのために大きなページ全体を "use client" にするのではなく、そのボタンだけを別コンポーネントに切り出して "use client" を付ける、という設計が本来正しい姿です。
まとめ
4つのレンダリング方式をおさらいします。
CSR(SPA)はブラウザ側で生成。ダッシュボードや管理画面向き。SEO不要でインタラクティブな画面に使う。
SSRはリクエスト時にサーバーで生成。ECサイトや予約サービス向き。ユーザーによって内容が変わる場面に使う。
SSGはビルド時に事前生成。ブログや企業サイト向き。更新頻度が低く全員に同じ内容を見せる場合に最速。
ISRはSSGの自動更新版。コンテンツが多いブログやドキュメント向き。SSGの速さとある程度の鮮度を両立する。
"use client" は「useState・useEffect・onClickなどブラウザでしか動かない機能を使うとき」だけに付ける。迷ったら付けないほうが正解に近い。
あなたが次にClaudeにページを作らせるとき、「このページはダッシュボードだからCSRで」「このページはブログ一覧だからSSGで」と一言添えてみてください。レンダリング方式を指定するだけで、生成されるコードの質と適切さが格段に上がります。
次回は認証とセキュリティの基本を解説します。ログイン機能の実装において「どこまでをSupabaseに任せてよいのか」「自前で作ってはいけないのはどこか」を整理します。
「自分のサービスはどのレンダリング方式が向いているかわからない」という場合は、無料相談をご利用ください。サービスの要件を聞いた上で、最適な構成を一緒に考えます。




