Next.jsのAPI呼び出しがよくわからない?内部APIと外部APIの使い分けを解説
こんにちは、とまだです。
みなさん、Next.jsでAPI呼び出しをしようとして「どうやるんだっけ?」と悩んだことはありませんか?
「API Routesとは?」 「内部APIと外部APIってどう違うの?」 「どこにコードを書けばいいの?」
実はNext.jsのAPI呼び出しには、いくつかの方法があるんです。
今回は現役のエンジニア、そして元プログラミングスクール講師としての経験から、Next.jsでのAPI呼び出しについて解説します。
Next.jsのAPI呼び出しは「お店」みたいなもの
Next.jsのAPI呼び出しって、お店の仕組みに似ています。
想像してみてください。
レストランで注文するとき。 お客さん(フロントエンド)が注文して。 厨房(バックエンド)が料理を作って。 ウェイター(API)が料理を運んでくれます。
Next.jsも同じです。
ブラウザがデータを欲しがって。 サーバーがデータを準備して。 APIがデータを届けてくれます。
でも、Next.jsの面白いところは...
自分のお店(内部API)も作れるんです。
なぜNext.jsはAPIも作れるの?
普通のReactだと、データが欲しいときは外のお店(外部API)に頼むしかありません。
でもNext.jsなら、自分のお店も開けます。
これがAPI Routesという仕組みです。
たとえば、こんなメリットがあります。
- APIキーを隠せる(お客さんに見せたくない情報を守れる)
- データベースに直接アクセスできる
- 複雑な処理をサーバー側で済ませられる
つまり、セキュリティ面でも安心なんです。
API Routesを作ってみよう
Next.jsでAPIを作るのは簡単です。
pages/api
フォルダにファイルを置くだけ。
たとえば、ユーザー情報を返すAPIなら...
// pages/api/users.js
export default function handler(req, res) {
const users = [
{ id: 1, name: "太郎" },
{ id: 2, name: "花子" },
];
res.status(200).json(users);
}
これだけで/api/users
というAPIができます。
シンプルですよね。
もう少し実用的にしてみる
実際のAPIでは、HTTPメソッドで処理を分けることが多いです。
// pages/api/users.js
export default function handler(req, res) {
if (req.method === "GET") {
// ユーザー一覧を返す
const users = [
{ id: 1, name: "太郎" },
{ id: 2, name: "花子" },
];
res.status(200).json(users);
} else if (req.method === "POST") {
// 新しいユーザーを追加
const newUser = req.body;
// ここでデータベースに保存する処理など
res.status(201).json(newUser);
} else {
// それ以外のメソッドは拒否
res.status(405).json({ message: "許可されていません" });
}
}
GETでデータを取得。 POSTでデータを追加。 それ以外は拒否。
RESTfulなAPIの基本形ですね。
フロントエンドからAPIを呼ぶ
作ったAPIをフロントエンドから呼んでみましょう。
一番シンプルなのはfetch
を使う方法です。
import { useState, useEffect } from "react";
export default function Users() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/api/users")
.then((res) => res.json())
.then((data) => {
setUsers(data);
setLoading(false);
})
.catch((error) => {
console.error("エラーが発生しました:", error);
setLoading(false);
});
}, []);
if (loading) return <div>読み込み中...</div>;
return (
<div>
<h2>ユーザー一覧</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
ローディング表示も入れました。
ユーザーを待たせないって大事ですよね。
サーバーサイドでデータを取得する方法
Next.jsなら、サーバー側でデータを取得することもできます。
これがgetServerSidePropsです。
// pages/users-ssr.js
export async function getServerSideProps() {
// サーバー側でAPIを呼ぶ
const res = await fetch("http://localhost:3000/api/users");
const users = await res.json();
return {
props: {
users, // コンポーネントに渡す
},
};
}
export default function UsersSSR({ users }) {
// すでにデータがあるのでローディング不要
return (
<div>
<h2>ユーザー一覧(SSR版)</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
この方法のメリットは?
- SEOに強い(HTMLに最初からデータが入ってる)
- 初期表示が速い(ローディング画面が出ない)
でも、サーバーに負荷がかかるので注意です。
エラー処理とセキュリティ
APIを作るとき、忘れちゃいけないのがエラー処理です。
エラー処理の基本
// pages/api/users/[id].js
export default async function handler(req, res) {
const { id } = req.query;
try {
// ユーザーを取得する処理
const user = await getUserById(id);
if (!user) {
return res.status(404).json({
message: "ユーザーが見つかりません"
});
}
res.status(200).json(user);
} catch (error) {
console.error("エラー:", error);
res.status(500).json({
message: "サーバーエラーが発生しました"
});
}
}
適切なステータスコードを返す。 エラーメッセージは親切に。 でも詳細すぎる情報は出さない。
バランスが大事です。
セキュリティの注意点
APIキーなどの機密情報は、必ず環境変数で管理しましょう。
// pages/api/weather.js
export default async function handler(req, res) {
// 環境変数からAPIキーを取得
const apiKey = process.env.WEATHER_API_KEY;
if (!apiKey) {
return res.status(500).json({
message: "設定エラー"
});
}
// 外部APIを呼ぶ
const weatherData = await fetch(
`https://api.weather.com/data?key=${apiKey}`
);
// クライアントにはAPIキーを含まないデータだけ返す
const data = await weatherData.json();
res.status(200).json(data);
}
APIキーはサーバー側だけで使う。 クライアントには絶対に渡さない。
これ、本当に大事です。
実務でよくある使い方
実際の開発では、こんな使い方をすることが多いです。
認証を含むAPI
// pages/api/protected.js
import { verifyToken } from "@/lib/auth";
export default async function handler(req, res) {
// トークンを確認
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
return res.status(401).json({
message: "認証が必要です"
});
}
try {
const user = await verifyToken(token);
// 認証済みユーザーのデータを返す
res.status(200).json({
message: "認証成功",
user
});
} catch (error) {
res.status(401).json({
message: "無効なトークンです"
});
}
}
データベースとの連携
// pages/api/posts.js
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
export default async function handler(req, res) {
if (req.method === "GET") {
// 投稿一覧を取得
const posts = await prisma.post.findMany({
orderBy: { createdAt: "desc" },
take: 10,
});
res.status(200).json(posts);
} else if (req.method === "POST") {
// 新しい投稿を作成
const { title, content } = req.body;
const post = await prisma.post.create({
data: { title, content },
});
res.status(201).json(post);
}
}
データベースへのアクセスもサーバー側で安全に。
まとめ
Next.jsのAPI呼び出しについて見てきました。
押さえておきたいポイントは...
pages/api
にファイルを置けばAPIができる- クライアントからは
fetch
で呼び出せる getServerSideProps
でサーバー側でも取得可能- エラー処理とセキュリティは必須
最初は内部APIから始めてみてください。
外部APIとの連携も、内部API経由にすれば安全です。
少しずつ慣れていけば、複雑な処理も書けるようになります。
著者について

とまだ
フルスタックエンジニア
Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。
著者の詳細を見る →