Blog Article
サーバーコンポーネントとクライアントコンポーネントについて

はじめに
Next.js を学び始めると、必ずと言っていいほど登場するのが「サーバーコンポーネント」と「クライアントコンポーネント」です。名前は難しそうですが、役割を正しく理解すると「なぜ分かれているのか」「どう使い分けるべきか」が自然と見えてきます。
まずは 2 つのコンポーネントの概要を説明し、その後にそれぞれの特徴や実装方法、使い分け、そしてサーバーからクライアントへ props を渡す流れまでを解説します。
参考にしたリンク
- https://nextjs.org/docs/app/building-your-application/rendering/server-components
- https://nextjs.org/docs/app/building-your-application/rendering/client-components
- https://react.dev/reference/react/useState
サーバーコンポーネントとは何か
サーバーコンポーネントとは、その名の通り「サーバー上で実行されるコンポーネント」です。ブラウザではなく、Next.js が動いているサーバー側で処理され、HTML の形になってからブラウザに送られます。一言で言うなら、「画面を作る前の重たい仕事を担当する存在」です。
データベースからデータを取得したり、API にアクセスしたり、外部サービスと通信したりといった処理を、安全かつ効率よく行うために使われます。
サーバーコンポーネントでできること
サーバーコンポーネントでできることを一言でまとめると、「安全に、効率よくデータを扱うこと」です。
サーバー上で動くため、次のような処理が可能です。
- データベースへの直接アクセス
- 環境変数や秘密鍵の使用
- 重たい計算処理
- API からのデータ取得
これらはブラウザで行うと、セキュリティやパフォーマンスの問題が出やすい処理です。そのため、サーバーコンポーネントに任せることで、安心してアプリを作ることができます。
いつサーバーコンポーネントを使うのか
サーバーコンポーネントは、「画面を表示する前に必要な情報を集めたいとき」に使います。
たとえば、ブログ記事一覧ページを考えてみてください。記事のタイトルや本文は、データベースや外部 API から取得する必要があります。このような処理は、ユーザーが何か操作する前に完了している方が自然です。そのため、「最初に表示する画面を作るための処理」は、サーバーコンポーネントに向いています。
なぜサーバーコンポーネントが必要なのか
もしすべてをクライアントコンポーネントで作った場合、次のような問題が起きます。
- ブラウザに不要な JavaScript が大量に送られる
- 秘密情報を安全に扱えない
- 初期表示が遅くなる
サーバーコンポーネントがあることで、「ブラウザに送らなくていい処理」をサーバー側で完結させることができます。
これにより、表示速度が向上し、セキュリティも保たれます。
サーバーコンポーネントの実装方法
Next.js の App Router では、特別な指定をしない限り、コンポーネントは自動的にサーバーコンポーネントになります。
// app/posts/page.tsx
export default async function PostsPage() {
const posts = await fetch("<https://example.com/posts>").then(res => res.json());
return (
<div>
<h2>記事一覧</h2>
{posts.map((post: any) => (
<p key={post.id}>{post.title}</p>
))}
</div>
);
}このコードでは、fetch を使ってデータを取得していますが、これはサーバー上で実行されます。
その結果だけが HTML としてブラウザに送られます。
クライアントコンポーネントとは何か
クライアントコンポーネントは、ブラウザ上で動作するコンポーネントです。ユーザーがクリックしたり、入力したりした操作に反応して画面を変える役割を持ちます。
一言で言うなら、「ユーザーと直接やり取りする存在」です。
React の useState や useEffect といったフックを使えるのが特徴で、インタラクティブな UI を作るために欠かせません。
クライアントコンポーネントでできること
クライアントコンポーネントを一言で表すなら、「ユーザー操作に反応できるコンポーネント」です。
次のようなことができます。
- ボタンをクリックして画面を切り替える
- フォーム入力をリアルタイムで反映する
- モーダルやアコーディオンの開閉
これらは、ユーザーの操作に応じて状態が変わるため、ブラウザ上での処理が必要です。
いつクライアントコンポーネントを使うのか
クライアントコンポーネントは、「ユーザーの操作によって画面が変わるとき」に使います。たとえば、いいねボタンや、入力フォーム、タブ切り替えなどが該当します。
これらはサーバーで完結できず、ユーザーの操作を即座に反映する必要があります。
なぜクライアントコンポーネントが必要なのか
もしすべてをサーバーコンポーネントで作ろうとすると、次の問題が起きます。
- クリックするたびにサーバー通信が必要になる
- 操作のたびに画面が再描画され、体験が悪くなる
クライアントコンポーネントがあることで、ブラウザ内で素早く状態を更新でき、快適な操作感を実現できます。
クライアントコンポーネントの実装方法
クライアントコンポーネントを作るには、ファイルの先頭に "use client" を記述します。
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
クリック数: {count}
</button>
);
}この宣言があることで、「このコンポーネントはブラウザで動く」ということを Next.js に伝えています。
サーバーコンポーネントからクライアントコンポーネントへ props を渡す流れ
処理は重いものほどサーバーで行い、操作はクライアントに任せる、という考え方が基本です。サーバーコンポーネントで取得・加工したデータを、props としてクライアントコンポーネントに渡します。クライアント側は、そのデータを使って画面操作を行います。
実際の流れ
// サーバーコンポーネント
import ClientPost from "./ClientPost";
export default async function Page() {
const post = await fetch("<https://example.com/post/1>").then(res => res.json());
return <ClientPost post={post} />;
}
"use client";
export default function ClientPost({ post }: { post: any }) {
return <h3>{post.title}</h3>;
}
このように、サーバーで取得したデータをそのまま props として渡します。
クライアントは「受け取ったデータを使って表示や操作をするだけ」です。
サーバーからクライアントへ渡せるもの、渡せないもの
サーバーからクライアントへ渡せるのは、「JSON に変換できるデータ」のみです。
渡せるもの
- 文字列
- 数値
- 配列
- オブジェクト(中身が JSON 形式のもの)
渡せないもの
- 関数
- クラスのインスタンス
- Date オブジェクト(そのままでは不可)
渡せないものを無理に渡そうとすると、エラーが発生します。
これは、サーバーとクライアントが別の実行環境で動いているためです。
具体例
処理内容 | 適したコンポーネント |
|---|---|
記事データ取得 | サーバーコンポーネント |
記事一覧表示 | サーバーコンポーネント |
いいねボタン | クライアントコンポーネント |
フォーム入力 | クライアントコンポーネント |
まとめ
- サーバーコンポーネントは、重たい処理やデータ取得を担当します。
- クライアントコンポーネントは、ユーザー操作に反応する UI を担当します。
- 処理はサーバー、操作はクライアントという役割分担が重要です。
- サーバーからクライアントへ渡せるのは JSON に変換できるデータのみです。
この考え方を意識することで、Next.js の設計が一気に理解しやすくなります。
ブログや Web アプリを作る際は、「これはどちらの仕事か?」と考えながら実装してみてください。