\n
日本AIセンター 社内教材
EV充電サービスを題材に、Web・データベース・AI駆動開発の土台を43ステップで体験する。基本・中級・上級のボタンで絞り込める。ボタンは全部押してよい。壊れたらリロードすれば直る。
学ぶ順序
基本=インターネットと画面の仕組み/中級=サービスを作る道具/上級=現場の事故と対策。STEP 41が総仕上げ。
STEP 0
これから触る全部の実験は、この3つの箱のどこかで起きている。まずこの地図だけ頭に入れる。
Webサービスの登場人物は3つしかない。あなたのスマホやPCで動くブラウザ(客席)、データセンターで動くサーバ(厨房)、そしてデータを保存するデータベース(冷蔵庫)。客席で「充電履歴を見せて」と注文すると、厨房が冷蔵庫から材料を出して料理し、完成した画面を客席に運ぶ。この往復がWebのすべてだ。
今回の題材は会員制のEV充電サービス。会員がアプリで充電し、履歴が記録され、料金が請求される。この教材で使う言葉づかい(Next.js・Prisma・PostgreSQL)は、実際の現場でそのまま使われている本物の道具の名前だ。
この3語は初心者が必ず混同する。でも対立語ではなく、大きい箱の中に小さい箱が入っている入れ子だと分かれば一発だ。切り口が違うだけ——サーバは「どこで」、バックエンドは「何を」、APIは「どう繋ぐ」。
プログラムが動くコンピュータそのもの。建物にあたる(AWS・Cloudflareの1台)
サーバ上で動く裏側のプログラム一式。厨房まるごと。中身は複数の役割:
バックエンドの中の「外から注文を受ける窓口」だけ。/api/spots のような入口。奥の調理は外から見えない
だから「バックエンド=API」と感じるのは自然だ——外から見ると、バックエンドの中で唯一見える入口がAPIだから。フロント開発者にはバックエンドが「APIの集まり」に見える。奥にあるビジネスロジックやDBアクセスは、窓口の内側に隠れている。混ざりそうになったら「場所・処理・入口」の3語を思い出す。
STEP 1
「/history」の「/」って何? の答え。URLは「建物の住所+部屋番号」でできていて、ページとは部屋そのもののこと。
URLはブラウザの上部に出ている、あの長い文字列だ。呪文に見えるが、実は郵便の宛名と同じ構造をしている。ドメイン=建物の住所(例:plugo.jp。世界に1つしかない)、パス=建物の中の部屋番号(例:/history。スラッシュで始まる部分)。そしてページとは、部屋の1つ1つのことだ。部屋に入ると1画面ぶんのHTML(画面の設計図)が出てくる。「充電履歴のページ」=「plugo.jpという建物の、/historyという部屋」。
ちなみにこの教材のURLにある「pages.dev」は、Cloudflare Pagesという「建物を貸してくれるサービス」の名前。自前の建物(独自ドメイン)を持たず、貸しビルの一室を借りている状態だ。
URLの分解
Q. https://plugo.jp/history の「建物」と「部屋」はそれぞれどこ?
建物=plugo.jp(ドメイン)、部屋=/history(パス)。https://は「渡し方のルール」(封をして安全に運ぶ約束)。
STEP 2
「plugo-like.jp」と打った0.1秒後、裏で何が起きているか。実はコンピュータは名前を理解できず、番号しか分からない。
コンピュータ同士はIPアドレスという番号(例:203.0.113.7)で相手を見つける。だがそんな番号は人間が覚えられないので、「名前→番号」を引ける世界規模の電話帳が用意されている。それがDNSだ。URLを開くたび、ブラウザはまずDNSに問い合わせて番号を手に入れてから、その番号に接続しに行く。
ログ
Q. DNSが止まると、サーバは元気でもサービスは開けなくなる。なぜ?
名前を番号に変換できないと、そもそもどこに接続すればいいか分からないから。住所録を失った郵便局と同じ状態になる。
STEP 3
ブラウザは常に「ください」とお願いしている。そのお願いの宛先に、人間用の窓口と機械用の窓口の2種類がある。機械用の窓口の名前がAPI。
URLを開くとき、裏では必ず「お願い」と「返事」の往復が起きている。お願いをリクエスト、返事をレスポンスと呼ぶ。お願いには種類があり、代表は2つ:GET=「見せて」(取得)、POST=「これを受け取って」(送信・作成)。
そして重要なのが、同じ建物の中に窓口が2種類あること。ページの窓口は人間のブラウザ向けで、返事はHTML(画面の設計図)。APIの窓口は機械向けで、返事はJSON(データだけ。飾りなし)。APIとは「プログラム同士がやり取りするための窓口」のことで、部屋番号を /api/ で始めるのが世界共通の慣習だ。スマホアプリも充電器も、画面は要らずデータだけ欲しいので、みんなAPIの窓口に並ぶ。
送ったお願い(リクエスト)
ボタンを押す
返ってきた返事(レスポンス)
—
Q. スマホアプリは、ページの窓口とAPIの窓口のどちらを使う?
API。アプリは画面(見た目)を自分の中に持っていて、サーバに欲しいのは中身のデータだけだから。同じ理由で充電器も他社システムもAPIに並ぶ。
STEP 4
インターネットはバケツリレーなので、途中に必ず「中継者」がいる。ハガキで送るか、封筒で送るか。
リクエストは何台もの中継機器を経由して届く。http(sなし)はハガキ——途中の誰からも中身が丸見えだ。httpsは暗号化という封をした封筒——中継者には意味不明な文字列にしか見えず、宛先のサーバだけが封を開けて読める。今どきsなしのサイトにパスワードを入れてはいけない理由を、下で目撃してほしい。
途中の中継者から見えるもの
—
宛先のサーバが読めるもの
—
Q. httpsなら、送った内容は誰にも読まれない。○か×か?
×。途中の中継者には読めないが、宛先のサーバは封を開けて読める。だから「どこに送るか」の判断は暗号化とは別に必要。
STEP 5
現代の画面づくりの根本思想を1つだけ学ぶ。「画面を直接いじらない。データを変えると、画面が勝手に付いてくる」。
Reactは画面を「部品(コンポーネント)」の組み合わせで作る道具だ。そして最大の発明は、画面をデータの鏡にしたこと。下の実験では、左の「データ」だけを操作する。右の「画面」を書き換えるコードはどこにも存在しないのに、画面は必ずデータに追従する。
特に「単価を変更」に注目。データを1箇所変えただけで、画面の全行の料金が一斉に描き直される。もし画面を手でいじる方式なら、行の数だけ書き換え漏れのリスクがある。鏡方式なら漏れは原理的に起きない。
データ(状態)— 触るのはこっちだけ
画面 — Reactが自動で描き直す
Q. 「単価変更」ボタンは画面の各行を書き換えるコードを持っている。○か×か?
×。単価というデータを1つ書き換えただけ。各行の再描画はReactが「鏡」として自動でやっている。
STEP 6
Webの画面は3つの言語の分業でできている。骨組みがHTML、見た目がCSS、動きがJavaScript。デザインを作る=主にCSSを書くこと。
ではプロはCSSをどう書くのか。部品ひとつひとつに色を塗るのではなく、まずデザイントークンという「ルール表」を作る。テーマ色は紫、角丸は16px、余白は18px——という変数の一覧表だ。ページ内の全部品はこの表を参照して描かれるので、表を1箇所書き換えれば、ボタンもカードもタグも一斉に変わる。STEP 5の「画面はデータの鏡」とまったく同じ思想が、デザインにも使われている。
下の実験では、左のルール表だけを操作する。右のUI部品を個別に塗り直すコードはどこにもないのに、全部品が追従することを確かめてほしい。
デザイントークン(ルール表)— 触るのはこっちだけ
画面 — 全部品がルール表を参照している
渋谷パーキング 2F
空き 3口 / 50kW
Q. サービス全体のボタン色を紫から緑に変えたい。CSSを何箇所直す?
トークン方式なら1箇所(ルール表の色変数だけ)。部品ごとに色を直接塗っていたら、ボタンの数だけ直して回ることになり、必ず塗り漏れが出る。
STEP 7
データベースの正体はExcelの表とほぼ同じ。違いは「命令文(SQL)で操作する」ことだけ。
データベースはテーブル(=シート)の集まりで、行=データ1件、列=項目。Excelと違うのは、何百万行でも速く、複数人が同時に触っても壊れず、プログラムから命令文で操作する点だ。その命令文の言語がSQLで、実務の9割はたった4種類:探して(SELECT)/書き足して(INSERT)/直して(UPDATE)/列を増やして(ALTER)。
下のボタンは日本語の指示。押すと、それがSQLに翻訳されて表が変わる。この「翻訳」を裏で自動でやってくれる道具がPrisma(通訳)だ。
日本語 → SQLへの翻訳(Prismaの仕事)
member テーブル
Q. 4つの命令のうち、「表の形そのもの」を変えるのはどれ?
ALTER。列が増減する=ヘッダー行が変わる。残り3つは中身(行)の操作。この違いがSTEP 18の伏線になる。
STEP 8
PythonもJavaもJavaScriptも、正体は同じ。「人間語と機械語(0と1)の間の通訳」であり、翻訳のされ方と得意分野が違うだけ。
コンピュータが直接理解できるのは機械語(0と1の列)だけ。人間には書けないので、人間が読み書きできる中間の言葉=プログラミング言語を書き、それを機械語へ翻訳してから実行する。翻訳には2流派ある:コンパイル=事前に全文翻訳しておく(Java・C。速いが手間)、インタプリタ=その場で逐次通訳する(Python・JavaScript。手軽)。下の実験で、同じ1つの命令が言語ごとにどんな姿になるかを見比べてほしい。
命令:「充電量12.5kWhに単価36円を掛けて、料金を表示して」
言語のボタンを押す
Q. コンピュータが翻訳なしで直接理解できるのはどれ?
機械語だけ。Python・Java・JavaScriptはすべて、実行前か実行中に機械語へ翻訳されている。だから「どの言語で書いても最後は同じ0と1」——STEP 42の積み木の話につながる。
STEP 9
JS・TS・Node・npm・React・Next.js——似た名前の道具たちの関係は、家系図を1枚見れば二度と混乱しない。
昔、JavaScriptという運転手はブラウザという車しか運転できなかった。2009年にNode.js——ブラウザの外(サーバや手元のPC)でJSを動かすエンジン(実行環境)——が生まれ、同じ運転手がサーバという2台目の車を運転できるようになった。これが「フロントもバックも同じ言語」の起点だ。Nodeとセットのnpmは世界最大の部品市場で、Prismaもここで配られている。そしてライブラリ=道具箱(自分が主役で、必要なとき道具を呼ぶ)、フレームワーク=骨組み(向こうが主役で、決められた枠に自分のコードをはめる)。家系図の各行をクリックして確かめてほしい。
解説
Q. Node.jsは新しいプログラミング言語である。○か×か?
×。言語はあくまでJavaScriptで、Nodeはそれをブラウザの外で動かすための実行環境(エンジン)。言語と実行環境の区別が付けば、この家系は迷わない。
STEP 10
どの言語にも「定番の骨組み」が1〜2個ある。名前と性格を知れば、案件票のFW欄からそのシステムの出自・年代・現場の空気まで読めるようになる。
復習:フレームワーク=骨組み(向こうが主役で、決められた枠に自分のコードをはめる)。そして骨組みの名前はシステムの身分証だ。Spring Bootとあれば大企業の基幹、Laravelなら中小Webの受託、Strutsなら20年選手のレガシー——名前1つで現場が透ける。まず書き比べで性格を体感し、図鑑で18人の登場人物を知り、最後のクイズで案件票を読んでみよう(TypeScript系は特に増殖中なので厚めに扱う)。よくある誤解を1つ先に:AngularはJavaではない。JavaとJavaScriptは「インドとインドネシア」くらい別物で、AngularはJavaScript側の家系だ(Java文化の会社がフロントにAngularを選びがちなので同居はしている)。
書き比べ:同じ処理を各フレームワークで書くと、性格がこんなに違う
お題とフレームワークを選ぶと、実際のコードが出る
フレームワーク図鑑(クリックで解説)
解説
案件票読解クイズ:FW欄からどんな現場か当てる(1/4問目)
Q. 案件票に「Struts」とあったら、何を読み取る?
2000年代生まれの骨組み=20年選手のレガシーシステム。つまり中身は「保守」か「モダンへのリプレイス」案件。新規開発でStrutsを選ぶ現場は今は存在しない。
図で振り返る①
ここまでの11ステップは、バラバラの知識ではなく「あなたの指がスマホに触れてから、画面が出るまで」の一本道の部品だった。番号を押せば各STEPに戻れる。
迷子になったらこの図に戻る。「いま学んでいるのは、この道のどこの部品か」が言えれば、基本は卒業だ。
STEP 11
STEP 0の地図が実際に動く。光る場所を目で追うこと。「どこで動いているか」が見える人と見えない人で、開発の会話力が段違いになる。
実験は3本。①ページを開く:ブラウザ→サーバ→DB→サーバ→ブラウザと一周する。サーバ上でページの部品(サーバコンポーネント)が実行され、完成したHTMLだけが客席に届くのがNext.js(App Router)の標準スタイルだ。②充電器がAPIで報告:今度はブラウザが一切関与しない。機械(充電器)がJSONというデータ形式で窓口(API)に報告し、DBに1行増える。③壊れたデータ:数値のはずの欄に文字が入ったデータは、DBに届く前に「型チェック」の検問で弾かれる。
ブラウザ(客席)
Next.jsサーバ(厨房)
ページの道
APIの道
PostgreSQL(冷蔵庫)
| date | kwh | price |
|---|
通信ログ
Q. ②を実行した直後、会員のスマホ画面に新しい履歴は見えている?
見えていない。DBに書かれただけで、画面は次にページを開き直したときに最新化される。この「ズレ」を理解しているかが初心者と実務者の分かれ目。
STEP 12
案件票に頻出する「Next.js(App Router)」の正体。約束は3つだけ——フォルダがURLになる・部品は厨房が標準・フォームには近道がある。
Next.jsにはページの作り方の旧方式(Pages Router)と、2023年頃からの現行標準App Routerがある。案件票がわざわざApp Routerと書くのは「新方式で書ける人か」を確認したいからだ(旧方式しか知らない経験者が大勢いる)。
約束1:フォルダの形が、そのままURLの形になる。appフォルダの中にhistoryフォルダを掘ってpage.tsxを置けば、/history というページが生える。フォルダ名を [id] のように角括弧にすると「可変の部分」になり、/history/123 でも /history/456 でも同じファイルが応答して、123という値を受け取れる。下の実験で、URLを押すとどのファイルが応答するかを確かめてほしい。
appフォルダの中身(プロジェクトの実物)
何が起きるか
約束2:部品は「厨房(サーバ)で動く」のが標準。App Routerでは、何も指定しなければ部品はサーバ側でだけ実行され、完成したHTMLだけが届く(サーバコンポーネント)。押した瞬間の反応や入力中のチェックなど、お客さんの手元で動く必要がある部品だけ、ファイル先頭に "use client" と名札を付けて客席に出す。どちらにすべきかの仕分けが、App Router設計の日常だ——下のクイズで感覚を掴んでほしい。
仕分けクイズ:この部品はサーバ? use client?(スコア 0 / 5)
約束3:フォームには近道がある。「プラン変更を保存」のようなフォーム処理は、昔は専用のAPIを別に作る必要があったが、App RouterではServer Actionsという仕組みで、フォームからサーバの関数を直接呼べる。ただしスマホアプリや充電器など「画面以外の相手」との窓口は、これまで通りREST API(route.ts)を立てる。使い分けはこうだ:自分の画面のフォーム=Server Actions、外部の相手=API。
Q. 何も指定せずに作った部品は、サーバとブラウザのどちらで動く?
サーバ。これがApp Router最大の変更点で、旧方式とは標準が逆。ブラウザで動かしたい部品にだけ "use client" の名札を付ける。
STEP 13
画面が変わることと、保存されることは、完全に別の仕事。ここを混同しないことが、この教材で一番大事な理解かもしれない。
いいねボタンを押すと数字が増える。だがその数字がブラウザのメモリの中だけにあるなら、再読み込みした瞬間に消える。本当に残すにはDBへの保存(API経由)が必要だ。そして本物のサービスは1クリックで「画面を即+1」と「裏でDBに保存」の2つを同時にやっている。
先に画面を変えてしまう方式を楽観的更新と呼ぶ(保存はたぶん成功すると楽観する)。Xのいいねがこれで、押した瞬間ハートが赤くなるが保存完了は待っていない。失敗したらそっと巻き戻す。逆に保存を待ってから画面を変える「慎重版」もある。使い分けの基準は失敗したときの実害:いいね程度なら楽観的に気持ちよく、課金や充電開始のような取り消せない操作は慎重に。
ブラウザ(画面のメモリ)
DB(like_count テーブル・本当の記録)
再読み込み後の画面はこの値から始まる
ログ
Q. 楽観的更新で通信が失敗すると何が起きる?(実験で確認してから答え合わせ)
一度増えた画面の数字が巻き戻る。ユーザーには「増えたのに戻った」と見えるので、いいね程度でしか許されない体験。だから決済では使わない。
STEP 14
なぜ一度ログインすると、次のページでも「佐藤さん」と覚えてくれているのか。サーバは実は誰のことも覚えていない。
リクエストは1回ごとに独立していて、サーバから見れば毎回「初対面」だ。そこでログイン成功時にサーバはCookie(ブラウザが自動で持ち歩く小さな会員証)を発行する。以降ブラウザは、同じ建物へのお願いに毎回自動で会員証を添付し、サーバは会員証を見て「佐藤さんですね」と分かる。ログアウト=会員証を破棄すること。
ブラウザのCookie入れ(会員証ケース)
(空っぽ)
ログ
Q. ログアウトすると何が起きる?
ブラウザの会員証(Cookie)が破棄される。サーバが何かを忘れるのではなく、次のお願いに会員証が付かなくなるので「どなたですか」に戻る。
STEP 15
運営会社でも、あなたのパスワードを見ることはできない。見ないのではなく、原理的に見えない仕組みで保存している。
パスワードをそのままDBに保存すると、流出した瞬間に全滅する。そこでハッシュ化——入力を、二度と元に戻せない別の文字列に変換する一方向の処理——をしてから保存する。ログイン時は、入力されたパスワードを同じ方法でハッシュ化し、ハッシュ同士を比較する。元に戻せなくても、一致するかどうかは判定できる。これが「照合はできるのに、誰も中身を見られない」からくりだ。
変換の記録(1文字違うと別物になるのを見る)
DBのmemberテーブル(password列の実物)
佐藤 | a1f8...c2(ハッシュのみ) 鈴木 | 9d3e...71(ハッシュのみ)
Q. 元に戻せないのに、どうやってログインの照合をしている?
入力された値を同じ方法でハッシュ化して、保存済みハッシュと比較する。元に戻す必要はなく、「同じ入力なら同じハッシュになる」性質だけで照合できる。
STEP 16
ログイン(あなたは誰か=認証)の次は「あなたに何を許すか=認可」。この2つは別の仕事。
定番の設計がRBAC(読み:アールバック。Role-Based Access Control=役割ベースのアクセス制御)。ユーザー個人に権限を1つずつ付けるのではなく、「一般会員」「サポート」「管理者」のような役割(ロール)に権限を付け、人には役割を割り当てる。人事異動のたびに権限を付け替えるのではなく、役割を変えるだけで済む。
Q. 認証と認可の違いを一言で?
認証=あなたは誰か(本人確認)。認可=あなたに何を許すか(権限)。ログインできても管理者ページが開けないのは、認証は通ったが認可がない状態。
STEP 17
表の設計の第一原則。同じ事実を2箇所に書くと、いつか必ずズレる。
正規化=データの重複を排除して、1つの事実を1箇所だけに置く設計。下の悪い例では、注文のたびに会員の住所を毎回コピーしている。この状態で引っ越しが起きると——実験で確かめてほしい。
テーブルの状態
Q. 悪い設計で起きた事故の名前は?
更新時異常。同じ事実が3箇所にあるせいで、1箇所だけ更新されて矛盾が生まれた。正規化はこの事故を構造的に不可能にする。
STEP 18
STEP 7のALTER(列を増やす)を、チーム開発で事故らせないための仕組み。正体は「変更通達文書の綴り」。
なぜ通達が要るのか。同じ表が複数の場所に存在するからだ——各メンバーの開発PC、テスト環境、本番。運用が始まってから「プラン列を足したい」となったとき、4箇所を手作業でバラバラに直せば必ずどこかでズレて事故る。そこで「◯月◯日付:member表にplan列を追加せよ」という通達ファイル(中身はALTER文)を作り、日付順に綴じる。どの環境でも、綴りを上から順に全部適用すれば必ず同じ形になる。
Prismaでは、設計図(schema.prisma)を書き換えてコマンドを打つと、この通達が自動生成される。①→②の順で押して、「設計図を変える」と「DBが変わる」が別の瞬間であることを確認してほしい。
schema.prisma(設計図・唯一の正)
migrationsフォルダ(通達の綴り)
DB(member テーブル)
ログ
Q. ①を押した時点(②の前)で、DBは変わっている?
変わっていない。設計図を書き換えただけ。migrateを実行して通達が発行・適用されて初めてDBの形が変わる。この2段階が「安全」の正体。
STEP 19
「ポイントを引いて、課金を記録する」。この2つの間でサーバが落ちたら?お金を扱う全システムの土台がこれ。
トランザクション(transaction=取引)は、複数のDB操作を「全部成功か、全部なかったことか」のどちらかにする仕組み。途中で失敗したらロールバック(全部巻き戻し)される。性質の頭文字をとってACID(読み:アシッド)と呼ぶ:Atomicity(原子性=全か無か)・Consistency(一貫性=矛盾を残さない)・Isolation(分離性=他人の処理と混ざらない)・Durability(永続性=確定したら消えない)。関連語として、同時に同じデータを触らせない鍵がロック、鍵の取り合いでお互い待ちになる事故がデッドロック。
ログ
Q. ACIDのAは何の略で、どういう意味?
Atomicity(原子性)。原子=それ以上分割できない、の意味で、複数の操作が「全部成功」か「全部なかったこと」のどちらかにしかならない性質。
STEP 20
現場に入った初日から使う道具。正体は「コードのセーブポイント管理」と「平行世界での安全な実験」。
Gitは変更履歴の管理道具だ。コミット=セーブポイントを打つこと。いつでも過去のセーブに戻れるので、壊すことを恐れず変更できる。ブランチ=平行世界を作ること。本流(main)に触らず実験し、うまくいったらプルリクエスト(PR)——「この変更を本流に合流させてください」という申請書——を出す。申請はレビュー(人間やAIの検査)を通ってから合流する。この教材で何度も出てきた「PR」「月200件」「AIレビュー」の舞台がここだ。
履歴(セーブポイントの列。●が現在地)
ファイルの中身(料金表.ts)
Q. ブランチで実験する利点は?
本流(main)を一切汚さずに試せること。失敗したらブランチごと捨てればよく、成功したらPRのレビューを通して安全に合流できる。
STEP 21
テストは書く量より「配分」。全部を丁寧にやろうとすると、逆に品質が下がる。
テストは3階建てで考える。単体テスト(部品1個の確認。速い・安い)、結合テスト(部品をつないだ確認)、E2E(読み:イーツーイー。End to End=ユーザー操作を頭から最後まで通す確認。遅い・壊れやすい)。定石の配分がテストピラミッド——下の階ほど多く、上の階ほど絞る。これを逆にする(E2Eだらけ)と、実行に何時間もかかり、画面の小さな変更で毎日どこかが壊れる「不安定テスト地獄」になる。
Q. なぜE2Eを絞る?
遅くて壊れやすいから。1本の価値は高いが、増やすほど実行時間が伸び、画面変更のたびに直す保守費がかさむ。重要な動線だけに絞り、細かい確認は下の階でやる。
STEP 22
アジャイル開発の代表的な型。用語が5つ分かるだけで、現場の会議が字幕付きになる。
ウォーターフォール(最初に全部決めて順番に作る)との違いは、優先順位を毎週並び替えながら、短い区切りで作っては見せること。区切りをスプリント(1〜2週間)、やることリストをバックログ(優先順位付き)、毎朝の15分共有をデイリースクラム(朝会)、チームが1スプリントで消化できる量をベロシティ(読み:ベロシティ。velocity=速度)、スプリント末の反省会をレトロスペクティブ(ふりかえり)と呼ぶ。
Q. ベロシティは何のために測る?
将来の見積もりのため。過去数スプリントの実績消化量から「次も同じくらい」と予測する。個人の成績表にした瞬間、数字が盛られて壊れる(グッドハートの法則)。
STEP 23
時間のかかる処理をどう扱うか。待ち方の設計はUXの設計そのもの。
同期=レジの前で処理が終わるまで立って待つ。単純だが、待っている間は何もできない——画面が固まる。非同期=番号札をもらって席で待つ。受付だけ済ませて手元は自由、完了したら呼ばれる。AI処理やファイル変換のような数秒〜数分かかる仕事は非同期が定石だ。下の実験では、処理中に「反応チェック」ボタンを連打して、画面が生きているかを確かめてほしい。
ログ
Q. 同期実行中に反応チェックを押すとどうなった?なぜ?
押せない(反応しない)。処理が終わるまでその場を離れられないのが同期。ユーザーには「固まった」に見えるので、長い処理を同期でやってはいけない。
STEP 24
普通のHTTPは客からしか話せない。「充電が終わったら教えてほしい」をどう実現するか。
HTTPは常に「客→サーバ」の一方通行なので、最新状態を知るには定期的に聞きに行くしかない(ポーリング=数秒おきに「変わった?」と聞き続ける方式。無駄撃ちが多い)。WebSocket(読み:ウェブソケット)は最初に1回だけ電話をつなぎ、あとはつなぎっぱなしの回線でサーバから即座にプッシュしてもらう方式。チャット、株価、充電器の状態表示——「今」が大事な画面の定番だ。
ログ
Q. ポーリングの2つの欠点は?
①変化がなくても聞きに行くので通信が無駄に多い ②次に聞きに行くまでのあいだ、最新情報が遅れる。WebSocketはどちらも解決するが、常時接続のコストを払う。
STEP 25
エラーは怖い呪文ではなく、犯人の残した指紋。読み方さえ知れば、原因の大半はログが教えてくれる。
障害対応の第一歩は「エラーメッセージを読むこと」。意外なほど多くの人が読まずに慌てる。メッセージには何が・どこで起きたかが書いてあり、パターンは有限だ。下の事件簿で、ログを読んで4人の容疑者から犯人を当ててほしい。
エラーログ(事件現場)
Q. ECONNREFUSED 127.0.0.1:5432 —— 5432という番号から何が分かる?
5432はPostgreSQLの標準の接続口番号。つまり「DBへの接続が拒否された」=DBが落ちているか、接続先の設定ミス。番号が犯人の指紋になる例。
図で振り返る②
中級の15ステップは「1つの機能が生まれてリリースされるまで」の工程の部品だった。上の道が機能の一生、下の道がそれを支えるチームの営み。
機能の一生
チームの営み(毎日回るサイクル)
面談で「開発の流れを説明して」と言われたら、この2本の道を上から話せばそれが答えになる。
STEP 26
「検索が遅い」の原因第1位。10万件から1人を探すのに、1ページ目からめくるか、五十音の索引で飛ぶか。
DBは何も工夫しないと、条件に合う行を探すために全行を上から順に確認する(フルスキャン)。10万件なら10万回。そこでインデックス(索引)——特定の列の値で引ける五十音順の目次——をあらかじめ作っておくと、目的の行へほぼ直行できる。ただし索引はタダではない:書き込みのたびに索引の維持コストがかかるので、「よく検索する列にだけ張る」のが設計だ。
Q. 全部の列にインデックスを張れば最速になる。○か×か?
×。索引は書き込みのたびに維持コストがかかるため、増やすほど書き込みが遅くなる。「よく検索する列にだけ」が正解。
STEP 27
同じ画面を作るのに、DBへの「聞き方」だけで所要時間が100倍変わる。ORM(通訳)任せで起きる最有名バグ。
会員100人の一覧に、それぞれの充電履歴を添えて表示したい。素朴に書くと「まず100人のリストをもらう(1回)→1人ずつ履歴を聞きに行く(100回)」で合計101回、冷蔵庫を開けることになる。これがN+1問題(Nは人数)。正解は「会員と履歴をまとめて1回でください」と聞くこと(SQLのJOIN、Prismaならincludeという書き方)。
DBに届いた質問(SQL)
Q. 会員が1万人になったとき、素朴な書き方のクエリ回数は?
10,001回。まとめて聞く書き方なら変わらず1回。人数に比例して遅くなるか、一定のままか、が本質的な違い。
STEP 28
よく聞かれる質問の答えを、毎回冷蔵庫まで取りに行かず手元のメモ帳に書いておく。ただし本当の難しさは「メモの消し時」。
「人気の充電スポット一覧」のような、みんなが見るのに滅多に変わらないデータは、毎回DBで重い集計をするのが無駄だ。そこで一度計算した答えをRedis(メモ帳役の高速な保管庫)に書き留め、次からはそこから返す。1回目(MISS=メモにない)は遅く、2回目以降(HIT)は一瞬——を体験してほしい。
そして「スポット情報が更新された」を押すとメモを破棄する。これを無効化と言い、キャッシュ設計の本丸はここ。無効化を忘れると「古い情報を返し続ける」事故になる。ちなみにAIのプロンプトキャッシュ(同じ前提文を割引価格で使い回す仕組み)も原理はこのメモ帳と同じだ。
ログ
Q. キャッシュがあるのに古い情報が表示され続けるバグ。原因はどこにある可能性が高い?
無効化の漏れ。データを更新する処理のどこかで「メモ帳を破棄する」一手が抜けている。
STEP 29
キャッシュ(STEP 28)の地球版。データは光の速さでも、東京〜ロンドンは往復で0.2秒かかる。
CDN(読み:シーディーエヌ。Content Delivery Network=コンテンツ配信網)は、世界中に置いた配布拠点にファイルのコピーを置き、ユーザーに一番近い拠点から配る仕組み。画像・JS・動画のような「誰に配っても同じもの」が対象で、会員ごとに違う中身(履歴など)は本体サーバの仕事のまま。ちなみにこの教材自体がCloudflareのCDNから配られている——Cloudflareは世界最大級のCDN事業者だ。
Q. 会員の充電履歴ページはCDNに置ける?
置けない(そのままでは)。人によって中身が違うから。ページの枠組みや画像はCDN、履歴データだけAPIで取る、という分担にするのが定石。
STEP 30
相手のAPIには「1秒に3件まで」のような利用上限がある。ぶつかると429エラー。人気店に10人で押しかけるか、並んで入るか。
まずA(制御なし)を押す。10件同時に送ると3件だけ成功し、7件が429(上限超過)で失われる。次にB。全件を行列(キュー)に積んで毎秒3件ずつ流し、途中で429を食らったら少し待って再送する——待ち時間を1秒、2秒、4秒と倍にしていく再送の定石を指数バックオフと呼ぶ。遅くはなるが1件も失わない。
この構造はAIのAPI(Claude・OpenAI)でも決済APIでも全く同じ。大量のファイルをAIに処理させるサービスが「安定稼働が難しい」と言われる理由の大半は、この流量制御の設計にある。
ログ
Q. 429エラーは「障害」か?
障害ではなく仕様。相手が「ペースを落として」と言っているだけなので、正しい対応は再送設計であって、エラー通知で人を起こすことではない。
STEP 31
STEP 30は「自分が外部を呼ぶ側」の混雑だった。今度は逆向き——「自分のサービスがユーザーから受ける側」の混雑がトラフィック。
トラフィック=自分のサービスに届くアクセスの量(交通量)。ここで大事なのは、会員数はトラフィックではないということ。会員8万人のサービスでも、同じ瞬間に使っているのは数百人だ。プロは「登録会員 → 月に使う人 → 1日に使う人 → いま同時に使っている人 → 秒間リクエスト数」と桁を落として換算する。ここで出てくる略語を2つ:DAU(読み:ディーエーユー。Daily Active Users=1日のうちに1回でも使った人の数)、RPS(読み:アールピーエス。Requests Per Second=1秒あたりにサーバへ届くお願いの数)。この概算(フェルミ推定)ができると必要なサーバ規模が見積もれて、過剰な分散設計も見積もり不足も避けられる。下のスライダーで換算の感覚を掴んでほしい。
この実験で使っている換算式(仮定つき)
※係数(÷4・÷25)はサービスの性質で変わる。毎日使うSNSなら÷4は÷1.5に近づくし、月1の手続きサービスなら÷10になる。大事なのは正確な係数ではなく、式を自分で立てて桁を掴むこと。
必要な構成の判定
Q. 「会員数が10倍になったらサーバも10台必要」——正しい?
雑すぎる。トラフィックは会員数でなく同時利用数で決まり、キャッシュが効けばDBへの負荷は線形には増えない。まず換算して、どこが最初に詰まるか(大抵はDB)を見るのが正しい順序。
STEP 32
「絶対に落とすな」はプロの言葉ではない。プロは「どこまで落ちてよいか」を数字で決める。
監視の3本柱:ログ(何が起きたかの記録)・メトリクス(数値の推移。エラー率や応答時間)・トレース(1リクエストが各層をどう旅したかの追跡)。その上でSLO(読み:エスエルオー。Service Level Objective=サービス品質の目標値)を決める。例:「稼働率99.9%」。そして重要なのがエラーバジェット=目標までの「使ってよい失敗の量」。予算が残っていれば攻めた変更をしてよく、使い切ったら安定化に専念する——障害を「あってはならないもの」から「予算管理の対象」に変える発想だ。
Q. エラーバジェットが残っているとき、チームは何をしてよい?
攻めた変更(新機能のリリースや実験)。失敗の予算内なら挑戦してよい、というのがこの仕組みの本質。使い切ったら安定化優先に切り替える。
STEP 33
世界で最も言われた言い訳「自分のPCでは動くんですけど」。原因は環境の差分。それを箱ごと運んで消した技術。
まず環境の分離:開発(各自のPC)・ステージング(本番そっくりの練習場)・本番の3段が基本で、接続先やAPIキーのような設定は環境変数で外出しし、鍵(シークレット)は専用の金庫サービスで管理する。その上でDocker(読み:ドッカー)——アプリを実行環境(Nodeのバージョンから設定まで)ごとコンテナという箱に詰め、どのマシンでも同じに動かす技術。箱を大量に並べて運用する管制塔がKubernetes(読み:クバネティス。略してk8s)だ。
ログ
Q. 環境変数に入れるべきものは?
環境ごとに変わる設定(DB接続先・APIキー・機能フラグ)。コードに書くと環境ごとにコードを書き換える羽目になり、鍵の流出事故も起きる。
STEP 34
リリースに失敗はつきもの。プロの差は「失敗しないこと」ではなく「失敗したとき何人に影響するか」の設計。
3つの型がある。一発切替(ビッグバン)=全員を一斉に新版へ。速いが失敗すると全員巻き込む。ブルーグリーン=新旧2面のサーバを用意してスイッチで切替。失敗しても旧面に即戻せる。カナリアリリース=まず1%のユーザーだけ新版へ流し、問題なければ徐々に広げる(炭鉱で毒ガスを検知したカナリアが由来)。
※新版にバグが潜んでいた想定で比較
Q. カナリアリリースの利点を一言で?
失敗の被害を1%に閉じ込めて、本番の実ユーザーで検証できること。テストで見つからないバグは必ずあるので、「本番こそ最後のテスト環境」と割り切った設計。
STEP 35
事故は「起きたら」ではなく「起きたとき」。守りの最後の砦は、戻れる場所があるかどうか。
バックアップ=ある時点のDBの完全な写しを、別の場所に取っておくこと。定期的(毎晩など)に自動で取るのが基本だ。そして重要な格言がある——「バックアップは、復元のリハーサルをして初めてバックアップと呼べる」。取ってあるつもりが壊れていて戻せない、が実際の事故で一番多い。下では、バックアップを取ってから事故を起こす順と、取らずに事故を起こす順の両方を試せる。
DB(member テーブル)
| id | name |
|---|
ログ
Q. バックアップを「取っている」だけでは不十分と言われるのはなぜ?
復元できて初めて意味があるから。復元手順のリハーサルをしていない現場は、事故当日に「戻し方が分からない・実は壊れていた」に直面する。
STEP 36
リプレイス案件の最難関。機能は作り直せるが、データは失敗したら取り返しがつかない。
移行の工程はETL(読み:イーティーエル。Extract抽出・Transform変換・Load投入)と呼ぶ。旧DBから抜き、新しい形に変換し(ここで必ず「汚れデータ」——全角数字・空欄・矛盾——が見つかる)、新DBに入れる。そして最重要が突合(とつごう)=新旧の全件を機械的に比較して1件も違わないことを確認する検証。この一連を本番と同じ手順で何度もリハーサルできるようにしておくことが、移行の品質そのものになる。
移行の進行
Q. 突合とは何をすること?
新旧DBの全レコードを機械的に比較して、差異ゼロを確認する検証。目視サンプル確認では8万件の中の12件の欠けを見つけられない。移行の合否は突合が決める。
STEP 37
ネットワークは必ず失敗し、失敗すると再送が起きる。そのとき課金が2回実行されたら大事故。全ステップの知識が合流する最終試験。
充電開始と同時に300円を課金する。ところが応答が届かず、アプリが同じ注文を自動再送した——さて課金は何回実行されるべきか? もちろん1回。これを保証する性質を冪等性(べきとうせい)と呼ぶ:同じ操作が2回届いても、結果は1回と同じ。
実現方法は拍子抜けするほど単純で、注文に一意の番号(冪等キー)を付け、サーバは「同じ番号の注文は2回実行せず、前回の結果だけ返す」。まずキーなしで二重課金の事故を起こし、次にキー付きで防がれるのを見てほしい。決済会社のAPIには必ずこの仕組みが備わっている。
ログ
DB(charge_payment テーブル)
| id | 金額 | 冪等キー |
|---|
Q. STEP 30のリトライ(再送)とSTEP 37の冪等性は、なぜセットで必要?
リトライは「失敗したらもう一度送る」仕組みなので、同じ注文が複数回届く状況を自ら作り出す。だから再送を設計するなら、受け手側の冪等性が同時に必須になる。攻め(リトライ)と守り(冪等性)は常に一対。
STEP 38
セキュリティの会話に入るための最低限の3つ。名前と手口を知らないと、対策の議論が聞き取れない。
①SQLインジェクション=入力欄にSQL命令を紛れ込ませ、DBを不正操作する攻撃。対策はプレースホルダ(入力を命令文と混ぜず、常に「ただのデータ」として渡す書き方)。②XSS(読み:エックスエスエス。Cross-Site Scripting)=投稿にスクリプトを仕込み、他人のブラウザで実行させる攻撃。対策はエスケープ(タグを無害な文字に変換)。③CSRF(読み:シーサーフ。Cross-Site Request Forgery)=ログイン中のユーザーを罠ページ経由で操作し、本人のふりして送信させる攻撃。対策は正規の画面にしか無い合言葉(トークン)の確認。
結果
Q. FWが守ってくれるのに事故が起きるのはどんなとき?
標準の守りを自分で外したとき。生SQLの文字列連結、エスケープの明示的な無効化など。「便利そうだから外す」場面こそレビューで止める箇所。
STEP 39
設計思想の有名な論争。答えは技術ではなく「チームの人数」にある。
モノリス=1つの大きなアプリとして作る(この教材のNext.js構成もこれ)。マイクロサービス=機能ごとに独立した小さなサービスに分け、API通信でつなぐ。マイクロの利点はチームごとの独立開発と個別スケール。ただし代償が重い——通信・整合性・監視・デプロイの全部が難しくなる(分散システムの複雑さを自分から招き入れる)。判断の物差しはコンウェイの法則(読み:コンウェイ。「システムの構造は組織の構造に似る」)で、サービスの数はチームの数に従うべき。
判定クイズ:この現場はどっち?(1/3問)
Q. まずどちらから始めるのが定説?
モノリス。分割は「チームが増えて開発が渋滞してから」で遅くない。最初からマイクロにすると、少人数で分散システムの複雑さと戦う羽目になる。
STEP 40
ここまでは「どう作るか」。最後は「それ、いくら・何ヶ月?」。技術を金額に翻訳できて初めて、仕事は成立する。
見積もりの通貨が人月(読み:にんげつ)=1人が1ヶ月フルで働く仕事量。5人月なら「1人で5ヶ月」でも「5人で1ヶ月」でも同じ量だ(1人月 ≒ 20人日)。作り方は拍子抜けするほど素朴で、機能を数えて、1機能あたりの人日を掛け、テストとバッファを足すだけ。厳密さより「桁が合っているか」が命——5人月の案件を50人月と見積もれば大事故、トラフィックのフェルミ推定(STEP 31)と同じ発想だ。下のスライダーで、機能の数がそのまま金額に変わる感覚をつかんでほしい。
計算の内訳(仮定つき)
Q. 「10人月削減しました」を面談で言うとき、必ず添えるべきものは?
分母。「40人月中10人月削減(≒25%)」のように割合と絶対値をセットにする。絶対値だけだと大きさが伝わらず、割合だけだと規模が見えない。両方あって初めて相場に馴染む。
図で振り返る③
上級の14ステップは2本の道に整理できる。「遅い」と言われたら上の道を左から順に疑い、「事故」に備えるなら下の道を左から順に敷く。
速さの道(「遅い」の犯人を探す順番)
守りの道(事故の前・最中・後)
お金の道(技術を仕事にする)
この3本の道と、図①の「タップの旅」、図②の「機能の一生」。地図は3枚だけだ。全43ステップはこの3枚のどこかに住んでいる。
STEP 41
最後は、この教材全体の裏テーマ。AIの出力の質は、AIの賢さではなく、指示の言語化の質で決まる。
AIに「いい感じにやって」と頼むと、毎回違う「いい感じ」が返ってくる。AIが悪いのではなく、「いい感じ」の定義を渡していないからだ。プロの指示書は4点を必ず埋める:入力(何を渡すか)・出力(どんな形で返すか)・判断基準(何を良しとするか)・禁止事項(やってはいけないこと)。この4点があると、出力は安定し、直したいときは指示書を直せば再発しない。実は「要件定義」も「タスク分解」も、やっていることはこれと同じ——曖昧なものを、実行可能な言葉に変換する仕事だ。
AIからの返答
—
指示書(プロの頼み方)
入力:7月の充電履歴データ 出力:日本語3行以内 判断基準:合計金額と前月比を必ず含む 禁止:データにない数値の推測
Q. AIの出力が毎回ブレるとき、最初に直すべきはAIの設定か、指示書か?
指示書。判断基準と出力形式が言語化されていないことがブレの主因。指示書を直せば、同じ修正がチーム全員のAI利用に効く。
STEP 42
この教材で学んだ全部は、実は1枚の積み木に収まる。一番下は電圧、一番上はあなたの気持ち。1回のタップの旅を見届けて修了。
ITの世界は層(レイヤー)の積み木でできている。各層は「すぐ下の層の使い方」だけを知っていて、中身は知らなくていい——アプリを書く人は電圧を知らないし、あなたがタップするときJSONを知らない。この「中身を隠して使い方だけ見せる」仕組みを抽象化と呼び、だからこそ人類は電子の物理から巨大なサービスまでを積み上げられた。エンジニアの職種(インフラ・バックエンド・フロントエンド・デザイナー・PM)も、実はどの層を担当するかの分業だ。
そして注目してほしいのが両端だ。一番上(人間の意思)と一番下(電圧)だけがアナログ——連続的で、曖昧で、無段階。真ん中だけがデジタルだ。デジタルとは、アナログな気持ちをアナログな物理現象で確実に運ぶための「中間の包装」だと言える。
第6層 人間の意思 アナログ
第5層 言葉とUI(画面・ボタン)
第4層 アプリ(コード・API・DB)
第3層 通信(DNS・パケット・HTTPS)
第2層 ビット(0と1)
第1層 物理(電圧・光・磁気) アナログ
Q. この積み木で「アナログ」なのはどの層?
両端。第6層(人間の意思=曖昧で連続的)と第1層(電圧・光=連続的な物理現象)。真ん中のデジタルは、この2つのアナログの間を確実に運ぶための包装。
ここまでの例えは入門のための地図であって、実物とは縮尺が違う。実務レベルに進む人のために、盛った箇所を正直に開示する。
STEP 7で「日本語の指示がSQLに翻訳される」と見せたが、Prismaの本当の翻訳元は日本語ではなくTypeScriptのコードだ。実際はこの2段翻訳になっている:
日本語の要望「プレミアム会員を探して」
↓ 人間かAIがコードに書く
await prisma.member.findMany({ where: { plan: "premium" } })
↓ PrismaがSQLに変換する
SELECT * FROM member WHERE plan = 'premium';ただし前半の「日本語→コード」をAIが担うようになったのがAI駆動開発なので、「日本語からSQLへ」は例えというより、半分現実になりつつある。
| 教材の例え | 本当のところ |
|---|---|
| DBは「Excelの表」 | 構造は同じだが本質差が3つ。インデックス(速く探す索引)、トランザクション(複数の変更を「全部成功か全部なかったことか」にする。課金で必須)、同時実行制御(大勢が同時に書いても壊れない)。Excelにはどれもない |
| 「完成したHTMLだけが届く。JSはほぼ不要」 | 最小限のJavaScriptも一緒に届き、HTMLに後から動きを接続する(ハイドレーション)。「ほぼ」に嘘はないがゼロではない |
| 「画面はデータの鏡。全行が描き直される」 | Reactは実際には全部描き直さず、変わった部分だけ差分更新する(仮想DOM)。思想は鏡、実装は賢い手抜き |
| Redisは「手元のメモ帳」 | 実際はサーバの中ではなく、独立したもう1台の高速保管サーバ。「厨房の隣の小さい冷蔵庫」が正確 |
| マイグレーション=「通達を上から順に適用」 | DB自身が「どの通達まで適用済みか」を記録する専用の表を持ち、二重適用を防いでいる。つまりここにも冪等性がいる |
| 冪等キー「同じ番号は2回実行しない」 | 番号を「覚えておく」には、その番号自体をDBに保存する必要がある。覚え場所の設計まで含めて冪等性の実装 |
| サーバ=「厨房1つ」 | 本番は厨房が複数台あり、負荷で増減する(オートスケール)。だからメモリ上のデータは他の厨房から見えず、共有したい状態はRedisやDBに置く——STEP 13の話は複数台になると更に重要になる |
例えで速く入門し、種明かしで実物に接続する。両方を知っていれば、現場の会話で例えのまま話して恥をかくことはない。
コンポーネント/状態/SQL/スキーマ/マイグレーション/サーバコンポーネント/API/JSON/型チェック/楽観的更新/N+1/キャッシュと無効化/レートリミット/指数バックオフ/キュー/冪等性/HTML・CSS・デザイントークン/ハイドレーション/App Router・use client/URL・パス/リクエストとレスポンス/JSON・API/DNS/HTTPS/Cookie・認証と認可/ハッシュ化/コミット・ブランチ・PR/同期と非同期/インデックス/バックアップと復元/指示書の4点セット/層(レイヤー)と抽象化/機械語・コンパイル/実行環境(Node)・npm/ライブラリとフレームワーク/各言語の定番FW(Spring・Laravel・Rails・FastAPI)/トラフィックとRPS・概算見積り/人月と見積もり/認可とRBAC/正規化/トランザクションとACID/テストピラミッド/スクラム/WebSocket/CDN/SLOとエラーバジェット/コンテナ(Docker)/ブルーグリーンとカナリア/ETLと突合/SQLインジェクション・XSS・CSRF/モノリスとマイクロサービス。これらは全部、現場の設計会議で今日も使われている言葉だ。次に仕様書やチケットでこれらの単語に会ったとき、頭の中でこのページのどこかが光れば、この教材の目的は達成されている。