Next.jsの画面とAPIが、どのようにひとつのWebアプリを形作るかを見ます。
重要なコードの抜粋へ ↓このページでわかること
- 画面とAPIの入口
- 利用者画面と管理画面の分離
- 入力から表示までの流れ
画面は役割ごとに置かれる
v1の画面は src/app の下に並びます。/login と /signup は入口、/app は利用者の操作画面、/admin は管理者用の画面です。URLとフォルダ構成を見比べると、アプリの輪郭がつかめます。
共通のレイアウトは各画面で再利用し、残高や履歴などの個別ページだけを差し替えます。
画面とAPIは別の責任を持つ
画面は入力と結果を分かりやすく見せます。APIはリクエストを受け、認証や入力形式を確認し、サービスやデータベース処理へ渡します。ブラウザから直接、帳簿の行を書き換える構成にはしません。
たとえば送金画面は送金先と金額を集めます。送金の正しさはAPIとデータベース側で改めて検証します。
先に見るべきファイル
最初は src/app/app/page.tsx と src/app/app/transfer/page.tsx を見ます。次に src/app/api/v1/transfers/route.ts を見ると、画面の操作がどのAPIに届くか追いやすくなります。
コードを読むときは細かな文法より、画面から次の処理へ渡す値に注目してください。
APIの約束を安定させる
画面とAPIは別々のコードです。入力項目、成功時の返り値、エラーコードを揃えておくと、画面側が状況に応じて説明できます。v1ではAPIを /api/v1 にまとめ、入力形式の検証や共通のエラー形式を使います。
画面だけの文言変更と、APIの意味を変える変更は影響範囲が違います。呼び出す側と受ける側の約束を意識すると、修正しやすいWebアプリになります。
入力フォームが受け持つ範囲
送金フォームは金額の入力を助け、送金先の確認を促せます。空欄や数字以外を早く知らせると使いやすくなります。しかしブラウザの検証は変更できます。APIでも形式を検証し、口座の所有や残高はさらに信頼できる場所で判定します。
画面の検証は利用者への案内、サーバー側の検証はシステムの約束を守るためです。両方を置く理由が違います。
待つ時間の設計
送金中に何も変わらない画面は、利用者に再クリックを促してしまいます。ボタンの状態、処理中の表示、完了後の履歴への案内を用意します。エラーの場合も「もう一度押してください」だけでは、既に送金が成立している可能性を説明できません。
表示を工夫しても通信の重複は起こり得ます。UIで連打を抑え、API側では同じ依頼を二重に処理しないという二段構えが必要です。
権限不足の見せ方
利用者が管理者のURLを直接開いたり、別の顧客のIDでAPIを呼んだりする場合を考えます。リンクを隠すだけでは防げません。サーバーで拒否し、画面には必要以上の内部情報を示さず、何ができないかを分かる形で伝えます。
一方で通信障害と権限不足を同じメッセージにすると、利用者は復旧を待つべきか操作を見直すべきか判断できません。エラーの種類を区別することがUIの品質につながります。
画面を増やしても迷わない構造
口座、履歴、送金、設定の画面を増やすと、どこに戻るか、今どの操作中かが分かりにくくなります。共通レイアウトと一貫したナビゲーションが役立ちます。スマホでは操作領域と本文の幅も確認します。
画面の見た目は飾りではなく、重要な取引の取り違えを防ぐ手段です。金額・送金先・確定のタイミングを読み違えにくくすることを優先します。
誰でも操作できる画面にする
残高やエラーを色だけで伝えると、色の違いが分かりにくい人には判断できません。金額、単位、状態を文字でも示し、キーボードで入力と確定を進められるようにします。送金のような重要操作では、確認画面で送金先と金額を読み直せることも大切です。
更新後に古い表示を残さない
送金が確定しても、画面の残高カードや履歴が古いままだと利用者は失敗を疑います。完了後に何を再取得するか、どの状態を一時的に表示するかを決めます。反対に、完了前に残高を先に減らして見せると、失敗時には表示を戻す必要があります。
銀行の操作では、見た目の即時性より、確定した結果と画面の説明が一致することを優先します。
重要なコードを読む
v1.0.0 の実コードから、この章で押さえたい箇所だけを抜粋しました。前後の定義は省略しています。
APIで入力を受け取る
TypeScriptconst json = await request.json().catch(() => ({}));
const parsed = createTransferSchema.safeParse(json);
if (!parsed.success) {
throw new ApiError("VALIDATION_ERROR", "Invalid request body.");
}まず理解するrequest.json() で送られたデータを読み、safeParse で決められた形か調べます。success が false なら、送金処理へ進まず入力エラーにします。
一歩深く画面側でも入力を確認できますが、APIは直接呼び出せます。ここでは形式だけを検証し、口座の所有者や残高など変わり得る業務条件は、後段の処理で確かめます。
出典:src/app/api/v1/transfers/route.ts