본문으로 건너뛰기

© 2026 Molayo

Zenn헤드라인2026. 05. 08. 21:05

それっぽい UI を AI が作れる時代に、フロントエンドは画面の意味を設計する

요약

AIが生成したUIは、単なる見た目の完成品ではなく、「仕様の仮説」として捉えるべきです。フロントエンドエンジニアは、このUIをレビューする際、表面的なデザインや操作フローだけでなく、画面上で扱われている「対象(ドメインモデル)」と、それが持つ状態、権限、データ構造といった背後にある意味を設計することが重要です。AIの出力を鵜呑みにせず、「このアプリは何をモノとして扱うのか」という視点から仕様の輪郭を定めることが、堅牢なアプリケーション開発の鍵となります。

핵심 포인트

  • AIが生成するUIは「完成品」ではなく「仕様の仮説」であると認識すべき。
  • フロントエンドエンジニアの役割は、見た目(View)だけでなく、画面の意味やドメインモデルを設計することにある。
  • レビューの際は、操作フローよりもまず「アプリが何をモノとして扱うか」(対象/エンティティ)に焦点を当てるべき。
  • AIが自動補完した仕様(例:ステータスバッジ、優先度など)は、必ず人間がその必要性や責務を判断し、採用するか決定する必要がある。

TL;DR

  • AI が作る UI は、完成した仕様ではなく、仕様の仮説を含んだ叩き台
  • AI が置いた UI パーツには、状態、権限、URL、DB、API などの未決定事項が混ざっている
  • フロントエンドがまず見るべきなのは、操作ではなく、画面上で何をモノとして扱うか
  • UI、URL、state、DB schema は、同じドメインモデルをそれぞれ別の形で表している
  • AI に UI を頼む前に、対象、状態、操作、URL、作らないものを小さく決めておくと、出力をレビューしやすくなる
  • AI 生成 UI をそのまま実装するのではなく、仕様の仮説として読み解くことが大事

はじめに

個人開発や社内ツールなどで、AI に UI を作らせると、画面はかなり速く出てきます。

管理画面、Todo アプリ、予約フォーム、経費申請、請求書一覧。

雑に頼んでも、カード、テーブル、サイドバー、検索フォーム、ステータスバッジ、モーダルくらいはすぐ並ぶでしょう。

Gemini Canvas に投げた例

最初はけっこう感動します。

でも、その画面をちゃんと実装しようとすると、急に手が止まることがあります。

- このステータスは何種類あるのか?
- 承認は 1 段階なのか、複数段階なのか?
- 却下された申請は再提出できるのか?
...

AI が出してくれたのは、画面の形です。

でも、画面の形があるだけでは実装できません。

その画面が何を表していて、何を変更し、どの状態を持ち、どのデータと対応するのかを決める必要があります。

この記事で言いたいことはただひとつです。

AI が作る UI は、完成品ではなく、仕様の仮説である。

だからこそフロントエンドは、その UI の見た目だけでなく、画面がどの対象を扱い、対象がどんな状態を持ち、誰がどの操作をでき、URL・state・API・DB 上でどの言葉で表現されるのか、を考える必要があります。

言い換えると、フロントエンドは画面の意味を設計する仕事でもあります。

AI が作る UI は、仕様の仮説である

AI にこう頼んだとします。

> 社内の「経費申請アプリ」を作りたいです。
> 申請一覧、申請詳細、承認ボタン、検索、ステータス表示がある UI を作ってください。
> Next.js でお願いします。

先に例示したように、見た目としては悪くない画面が返ってきます。

一覧画面には申請者名、金額、申請日、ステータスが並びます。

詳細画面には明細、コメント、承認ボタンがあります。

ステータスは DraftPendingApprovedRejected のようなバッジで表示されます。

それっぽいです。

でも、このそれっぽさの中には、AI が補った仕様が混ざっています。

バッジ 1 つでも仕様は要求される

たとえば、画面に Approved というバッジがあるとします。

見た目ではただのラベルです。

しかし実装では、少なくとも次のような判断が必要になります。

- 申請の状態は何種類あるのか?
- `approved` は最終状態なのか?
- `approved` になった日時を保存するのか?
...

バッジ 1 つでも、状態、権限、履歴、DB、API、画面表示に影響します。

AI が置いた UI 部品は、ただの装飾ではありません。

採用した瞬間に、仕様判断を要求してきます。

ここでレビューすべきなのは、バッジの色だけではありません。

そのバッジが、どの対象の、どの状態を表しているのかです。

AI が補った仕様を、人間が採用するか決める

AI が仕様を補うこと自体は悪くありません。

何もないところから叩き台を作るには便利ですし、自分では考えていなかった項目が出てくることもあります。

ただし、それを採用するかどうかは人間が決める必要があります。

AI が勝手に「支払い済み」ステータスを追加したなら、それは本当にこのアプリの責務なのか?

経費申請だけでなく、経理処理や支払い管理まで扱うことになるのではないか?

AI が勝手に「優先度」を追加したなら、誰が何のために使うのか?

優先度によって一覧の並び順、通知、承認期限が変わるのか?

AI が勝手に「添付ファイル」を追加したなら、今回はそこまで作るのか?

作るなら、アップロード、プレビュー、保存期間、ファイルサイズ、権限も考える必要があります。

AI がそれっぽく埋めたものを、そのまま仕様として受け入れると、あとから「画面にはあるけど仕様がない」ものが増えます。

だから、AI 生成 UI を見るときは、最初にこう考えます。

この UI は、どんな仕様に勝手に仮定しているのか。

まず何をモノとして扱うかを決める

では私たちは、仕様の輪郭をどこから決めればよいのでしょうか。

最初に見るべきなのは、操作ではなく対象です。

つまり、そのアプリが何をモノとして扱うのかです。

React 公式の Thinking in React では、UI をコンポーネントに分解し、それぞれの視覚的な状態を考え、最後にデータフローでつなぐ、という流れが説明されています。[1]

これは、見た目の分割だけの話ではありません。

どのデータがどの画面やコンポーネントに対応するのかを考えるきっかけになります。

AI が作った UI をレビューするときも同じです。

ボタンやカードの見た目だけを見るのではなく、その画面でユーザーが何を見て、何を操作しているのかを見ます。

操作より対象を見る

経費申請アプリを操作から考えると、こうなります。

  • 申請する
  • 承認する
  • 却下する
  • 検索する
  • 編集する
  • 再提出する

もちろん、これらの操作は必要です。

ただ、操作だけを先に考えると、画面が「やること」の単位で散らばりやすくなります。

そこで、先に対象を見ます。

この記事では、経費申請そのものをExpenseReport
と呼ぶことにします。

- `ExpenseReport`
- `ExpenseItem`
- `ApprovalStep`
...

ExpenseReport
は複数のExpenseItem
を持ちます。
承認を 1 段階より複雑に扱うなら、ApprovalStep
が必要になるかもしれません。
逆に、今回は 1 段階承認だけだと決めるなら、最初はApprovalStep
を作らない判断もできます。
申請者や承認者はEmployee
として扱うかもしれません。
こうやって対象が見えると、操作の置き場所も見えやすくなります。

- `ExpenseReport` を作成する
- `ExpenseReport` を提出する
- `ExpenseReport` を承認する
...

一覧画面はExpenseReport
の一覧。
詳細画面はExpenseReport
の詳細。
明細はExpenseReport
にぶら下がるExpenseItem

承認履歴は、必要ならApprovalStep
の一覧。
このように、まず対象を決めると、画面、コンポーネント、URL、state、DB schema の候補が自然につながり始めます。

AI が作った UI をレビューするときも同じです。
「このボタンは必要か」だけを見るのではありません。
「この画面でユーザーが触っている対象は何か」を見る。
ここを決めないまま UI を増やすと、あとで名前が揺れます。

名前の揺れは設計の揺れになる

名前が決まらないとき、単に命名センスがないわけではありません。
扱っている概念がまだ曖昧なことがあります。
この経費申請アプリでも、すぐに言葉が揺れます。

- 申請とレポートは同じなのか?
- 承認と確認は違うのか?
- 却下と差し戻しは違うのか?
...

この揺れは、UI のラベルだけに出るわけではありません。
コンポーネント名、URL、API、DB カラム、state 名、テスト名にも出ます。
フロントエンドでも、この言葉の揺れはそのまま効いてきます。
画面に表示するラベル、コンポーネント名、URL、API とのやり取り、state 名、テスト名が、ユーザーに見える言葉と近い距離にあるからです。

たとえば、今回のアプリでは次のように決めることにしましょう。

- `ExpenseReport` ... 経費申請そのもの。申請者、合計金額、状態を持つ。
- `ExpenseItem` ... 経費申請に含まれる明細。日付、用途、金額を持つ。
- `ApprovalStep` ... 承認者ごとの承認状態。(今回は 1 段階承認なので、最初は作らない)
...

これだけでも、AI の出力をレビューしやすくなります。
例えば AI が生成した UI に「支払い済み」というバッジが出てきたり、コード上にPaymentStatus
が出てきたりしたら、「今回は経費申請までで、支払い処理は扱わない」と判断できます。
AI が複数段階承認を前提にした画面やApprovalFlow
を出してきたら、「今回は 1 段階承認なので、まだ不要」と判断できます。
先に言葉を決めておくと、AI が補った仕様をそのまま受け入れるのではなく、今回のスコープに照らして採用するかどうかを判断できます。

名前を揃えることは、見た目を整えることではありません。
設計の揺れを減らすことです。

UI/URL/state/DB schema で、同じものを違う形で表す

対象と言葉が決まると、その影響は UI だけに閉じません。
確かに、フロントエンドが直接触るのは、コンポーネント、state、URL だけかもしれません。
でも、それらは API や DB schema と同じ言葉でつながっていないと、画面ごとに解釈がずれていきます。

ここで述べたいのは、全部を同じ形にしようということではありません。
UI のコンポーネント構造と DB のテーブル構造を一致させる、という話ではありません。
そうではなく、同じものについて話せる状態にする、という話です。

URL は「直接開ける対象」を表す

ここでは API エンドポイントではなく、ブラウザで開く画面 URL の話に絞ります。
経費申請アプリでExpenseReport
を主役にするなら、URL はたとえばこうなります。
それぞれ、次の対象を開く URL です。

- `/expense-reports` ... 経費申請の一覧
- `/expense-reports/new` ... 新しい経費申請の作成
- `/expense-reports/:reportId` ... 特定の経費申請の詳細
...

一方で、承認者のタスクを主役にするなら、別の形もありえます。

- `/approval-tasks` ... 承認者が処理すべきタスク一覧
- `/approval-tasks/:taskId` ... 特定の承認タスク詳細

この場合、ユーザーが直接触っている対象はExpenseReport
ではなくApprovalTask
かもしれません。
正解はアプリによって変わります。
重要なのは、ユーザーがどの対象を直接開けるものとして扱うのかを決めることです。
URL は DB テーブル名の写経ではありません。
ただし、URL が何を識別しているのかは、アプリのドメインモデルとつながっている必要があります。

Tim Berners-Lee の "Cool URIs don't change" では、URI を変わりにくい名前として扱う重要性が説明されています。[4]

ここで言いたいのは、URI の永続性そのものを深く論じることではなく、URL をただの画面遷移の都合として扱うと、あとから「この画面は何を識別しているのか」が曖昧になる、ということです。

ブックマークできるのか?

直接開けるのか?

共有できるのか?

戻るボタンで戻れるのか?

その URL は何を表しているのか?

ここには、アプリが何を対象として扱うかが出ます。

state は矛盾しない最小表現にする

ドメインモデルの曖昧さは、React の state にも出ます。

React 公式の state 構造の説明では、関連する state をまとめること、矛盾する state を避けること、冗長な state や重複した state を避けることが原則として挙げられています。[5]

たとえば、経費申請詳細画面で次のような state を持ったとします。

const [status, setStatus] = useState<"draft" | "submitted" | "approved">("draft")
const [isApproved, setIsApproved] = useState(false)
const [approvedAt, setApprovedAt] = useState<string | null>(null)

一見わかりやすく見えます。

しかし、この state はすぐ矛盾します。

- `status` は `approved` なのに、`isApproved` は `false`
- `isApproved` は `true` なのに、`approvedAt` は `null`
- `approvedAt` が入っているのに、`status` は `submitted`

こうなると、UI はどれを信じればよいのかわからなくなります。

approved

という状態に approvedAt

が必ず必要なら、その関係を型に出したほうが安全です。

type ExpenseReportStatus =
| { type: "draft" }
| { type: "submitted" }
...

これなら、approved

のときだけ approvedAt

を持つことが表現できます。

rejected

のときだけ reason

を持つことも表現できます。

これは単に型を凝った形にしたいからではありません。

UI が信じるべき事実を、矛盾しにくい形で 1 箇所に寄せるためです。

もちろん、実際のアプリでは API レスポンスや DB との変換もあります。

API や DB では status

approvedAt

が別フィールドになっているかもしれません。

それでも、画面で扱うモデルとして「この状態は何とセットで存在するのか」を考える価値はあります。

state 設計は、単に useState をどう分けるかの話ではありません。

画面が信じるべき事実を、どこにどう持つかの話です。

UI と DB schema は、同じ形ではなく同じ言葉でつながる

UI と DB schema は、同じ形である必要はありません。

UI には、見やすさ、操作しやすさ、情報の優先順位、ユーザーが理解しやすいまとまりがあります。

DB には、正規化、制約、履歴、監査ログ、インデックスなどの都合があります。

だから、DB のテーブルをそのまま画面に並べる必要はありません。

DB の expense_items は、画面では「明細」として見せるかもしれません。

DB の employeesdepartments が別テーブルでも、画面では申請者名と部署名を 1 行で見せるかもしれません。

監査ログが細かく保存されていても、画面では「承認履歴」として必要な情報だけを見せるかもしれません。

形は違っていいです。

ただし、画面で使う言葉と DB/API で使う言葉がずれていると、仕様の解釈が画面ごとに割れていきます。

たとえば、画面上では「申請」と呼んでいるものが、DB では requests 、API では reports 、コンポーネントでは Application と呼ばれている。

UI では「却下」と呼んでいる状態が、DB では failed のか rejected のか returned のか曖昧。

UI では「差し戻し後に再提出できる」と見せているのに、DB の状態遷移では終端状態として扱われている。

こうなると、画面ごとに解釈が割れます。

揃えるべきなのは、テーブル構造ではありません。

同じものについて話せる言葉です。

UI、URL、state、DB schema は、それぞれ別の設計対象です。

でも、見ているドメインモデルがずれていると、実装のあちこちに小さな矛盾が出ます。

AI 生成 UI をレビューするときに見ること

ここまでの話を、AI 生成 UI のレビュー観点としてまとめます。

AI が作った UI を見るときは、次の順番で見ると考えやすいです。

  • この画面の主役は何か?
  • その対象はどんな状態を持つか?
  • どの操作が、どの状態で許されるか?
  • URL で直接開ける対象は何か?
  • state は矛盾しない形になっているか?
  • DB/API の言葉と画面の言葉がずれていないか?
  • 今回あえて作らないものが混ざっていないか?

たとえば、AI が経費申請一覧に「支払い済み」バッジを追加してきたとします。

このときレビューすべきなのは、まずバッジの色ではありません。

「支払い済み」は ExpenseReport の状態なのか?
それとも、経理処理や支払い管理の状態なのか?
今回のアプリは支払い管理まで扱うのか?
扱わないならそのバッジは削るべきです。

AI が追加した UI をすべて否定する必要はありません。
ただし、採用するなら、それがどの対象の、どの状態や操作に対応するのかを決める必要があります。

AI 生成 UI は、完成した仕様ではありません。
あくまでも仕様の仮説です。

だから、見た目がきれいかどうかだけでなく、その仮説を採用するかどうかをレビューします。

AI に渡す前に、小さな設計メモを書こう

ここまで考えると、AI に UI を頼む前に、大層な要件定義書を書かないといけない気がしてきます。
でも、最初から完璧に決める必要はありません。
むしろ、小さく決めるほうがよいです。

毎回仕様を掘り起こすのではなく、AI に渡す前に、勝手に決めてほしくない最低限の前提を置いておくだけで、AI の出力はかなりレビューしやすくなります。

AI に渡す設計メモの例

たとえば、経費申請アプリなら、最初のメモはこのくらいで十分です。

このアプリは、社内の経費申請管理アプリです。
主役の対象は ExpenseReport です。
ExpenseReport は ExpenseItem を複数持ちます。
...

立派な仕様書ではなく、ただのメモです。
それでも、何もない状態で AI に頼むよりずっとレビューしやすくなります。

AI が画面を作ったあとに、次の観点で確認できます。

- 主役は `ExpenseReport` になっているか
- `status` は 4 種類に収まっているか
- 承認が複数段階になっていないか
...

このメモを先に渡しておくと、AI の出力を「使えるかどうか」だけでなく、「この前提に沿っているか」でレビューできます。

今回あえて作らないこと

もうひとつ大事なのは、作らないものを書くことです。

今回は次の機能を作りません。
- 支払い処理
- 複数段階承認
...

AI は曖昧なところをそれっぽく埋めます。
それは便利ですが、必要ない機能まで増える原因にもなります。
特に業務アプリは、ありそうなものがいくらでもありますよね。
経費申請なら、添付ファイル、通知、経理確認、支払い処理、部署、予算、締切、代理申請など。

でも、今回は作らないものもあります。
それを明示しておくと、AI の出力を小さく保てます。
人間側も「今回はここまで」と判断しやすくなります。

決めることと作らないことを分けておくと、AI が補った仕様に振り回されにくくなります。

まとめ

AI がそれっぽい UI を作れるようになっても、フロントエンドが考えることはなくなりません。
むしろ、考えるタイミングが少し手前に移ったように感じます。

  • 画面を作る前に、何を対象として扱うのかを見る。
  • その対象がどんな状態を持ち、どんな操作を受け付けるのかを考える。
  • URL で何を直接開けるのか、state が何と矛盾してはいけないのか、DB schema とどの言葉を共有するのかを揃える。
  • AI に任せる部分と、人間が判断する部分を分ける。

これらは一見、画面の外側にある設計のように見えるかもしれません。
でも実際には、どれも画面の見え方や振る舞いに返ってきます。

フロントエンドはたしかに、きれいな画面を作る仕事でもあります。
でも、その画面は見た目だけでできていません。

データ、状態、URL、権限、エラー、言葉、ユーザーの理解のすべてが画面に出ます。

AI が UI を速く作れるようになったことで、そこがより見えやすくなりました。

AI が作る UI は、完成した仕様ではありません。
あくまで仕様の仮説です。

その仮説を見て、何を採用し、何を捨て、どの言葉でコードに落とすのか。
それを考えることこそが、AI が UI を作れる時代のフロントエンドの大事な仕事だと思います。

おわりに

なにかありましたら X ご連絡よろしくお願いします。

参考文献

  • Thinking in React。React で UI をコンポーネントに分け、state を見つけ、データフローでつなぐ考え方を説明している公式ドキュメント ↩︎

  • オブジェクト指向 UI デザイン ― 使いやすいソフトウェアの原理。タスクではなくオブジェクトを起点に UI を設計する OOUI の考え方と設計プロセスを説明している書籍紹介ページ ↩︎

  • Ubiquitous Language。開発者とユーザーのあいだで共有する厳密な言葉として、ユビキタス言語の考え方を説明している Martin Fowler の記事 ↩︎

  • Cool URIs don't change。URI を変わりにくい名前として扱う重要性と、URL 設計で事前に考えるべきことを説明している W3C の記事 ↔︎

  • Choosing the State Structure。関連する state をまとめること、矛盾する state や冗長な state を避けることなど、React の state 設計原則を説明している公式ドキュメント ↩︎

AI 자동 생성 콘텐츠

본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
4

댓글

0