APIって結局何? フロントとバックエンドの間で何を渡してるのか、 めちゃくちゃ分かりやすく整理してみた

目次
APIって結局何?フロントとバックエンドの間で何を渡してるのか、めちゃくちゃ分かりやすく整理してみた
Next.jsやLaravelを触っていると、APIという言葉が普通に出てきます。
const res = await fetch('/api/articles')
const data = await res.json()みたいなコードもよく書きます。
自分もAPIを作ったり呼んだりはしています。
でも、
APIって何?
と改めて聞かれると、
フロントとバックエンドでデータをやり取りするやつ。
くらいの説明になりがちです。
間違いではないのですが、それだけだと、
endpointって何?
GETとPOSTは何が違う?
headerとbodyは何を入れる?
JSONはAPIそのもの?
200とか404は誰が返してる?
認証はどこで入る?
あたりが全部バラバラに見えます。
そこで今回は、APIを初めて触る人でも、
ブラウザから注文を出して、バックエンドが処理し、結果が返ってくる
という一本の流れで理解できるように整理してみます。
そもそもAPIは「ソフトウェア同士の受付ルール」
APIは Application Programming Interface の略です。
MDNでは、APIを、あるソフトウェアと別のソフトウェアやハードウェアがやり取りするための機能や規則の集まりとして説明しています。
参考: https://developer.mozilla.org/ja/docs/Glossary/API(外部サイト)
つまりAPIは、Webサーバーだけの言葉ではありません。
ブラウザには、
Geolocation API
Web Animations API
Fetch API
などがあります。
OSやライブラリにもAPIがあります。
なので、
API = REST API
API = JSONを返すURL
ではありません。
APIという言葉自体はもっと広く、
「このルールで呼んでくれれば、この機能を使えます」というソフトウェア同士の窓口
くらいに考えると分かりやすいです。
その中でもこの記事では、Web開発でよく使う HTTP API を中心に見ていきます。
Web APIは「レストランの注文」で考えると分かりやすい
少し雑に例えます。
フロントエンドをレストランの客。
バックエンドを厨房。
APIをホールスタッフや注文窓口だとします。
客が厨房へ直接入り、
冷蔵庫開けて、肉出して、自分で焼きます
とは普通なりません。
客はメニューを見て、
ハンバーグ1つください
と注文します。
注文を受けた側が厨房へ伝える。
厨房が処理する。
完成した料理が客へ返ってくる。
Web APIもかなり似ています。
フロントエンド
↓ request
API
↓
バックエンドの処理
↓
DBなど
↓
API
↓ response
フロントエンドフロントエンドがDBへ直接、
usersテーブルの3行目を今から勝手に書き換えます
とやるのではなく、
このユーザー情報を更新してください
という決められた窓口へrequestを送ります。
バックエンド側で、
入力は正しいか
ログインしているか
このデータを変更する権限があるか
DBへ何を保存するか
を判断し、結果を返します。

requestとresponse、この2つがまず基本
HTTPはクライアントとサーバーの間でメッセージをやり取りします。
MDNでは、クライアントから送られるメッセージを request、サーバーから返されるものを response と説明しています。
参考: https://developer.mozilla.org/ja/docs/Web/HTTP/Guides/Overview(外部サイト)
たとえば記事一覧を取得するとします。
フロント側から、
GET /api/articlesというrequestを送る。
バックエンドが処理して、
HTTP/1.1 200 OK
Content-Type: application/jsonと一緒に、
[
{
"id": 1,
"title": "APIって結局何?"
}
]のようなresponseを返す。
かなり単純化すると、
request = お願い
response = そのお願いへの返事
です。
HTTPの標準であるRFC 9110でも、クライアントがrequestを作成し、サーバーがそれを解釈してresponseを返すモデルとして定義されています。
参考: https://www.rfc-editor.org/rfc/rfc9110.html(外部サイト)
endpointは「どの窓口に頼むか」
APIを触っているとendpointという言葉が出てきます。
たとえば、
GET /api/articles
GET /api/articles/123
POST /api/articlesのようなURLです。
厳密にはAPI設計によって表現は変わりますが、初心者向けには、
endpoint = APIへアクセスする窓口の場所
くらいで考えると分かりやすいです。
レストランで、
注文受付
会計
テイクアウト受付
が別れているようなものです。
URLだけでなく、次に出てくるHTTP methodとセットで、
「どこに、何をしてほしいのか」
を表します。
GETとPOSTは「同じURLでもお願いの種類が違う」
HTTPにはrequest methodがあります。
RFC 9110では、methodはクライアントがそのrequestで何をしたいのかを示す主要な情報として定義されています。
参考: https://www.rfc-editor.org/rfc/rfc9110.html#name-methods(外部サイト)
よく使うものはこのあたりです。
GET
データを取得したい。
GET /api/articlesなら、
記事一覧をください
というイメージです。
POST
データを送って、サーバー側で処理してほしい。
POST /api/articlesなら、
この内容で新しい記事を作ってください
のような用途です。
PUT / PATCH
既存データを更新するときに使われます。
PUTとPATCHは同じ意味ではありません。
一般にPUTは対象の表現全体を置き換える意味を持ち、PATCHは部分的な変更に使われます。
DELETE
対象を削除したい。
DELETE /api/articles/123なら、
ID 123の記事を削除してください
というrequestです。
ただし、
GETなら必ずDBをSELECTする
POSTなら必ずINSERTする
という意味ではありません。
HTTP methodはrequestの意味・意図を表すものです。
実際にサーバー内部で何をするかはAPI側の実装によります。
headerは「注文票の端に書いてある補足情報」
requestにはURLやmethodだけでなく、headerも付けられます。
MDNではHTTP headerを、requestやresponseに追加情報を渡すためのものとして説明しています。
参考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference(外部サイト)
たとえば、
Content-Type: application/json
Authorization: Bearer xxxxx
Accept: application/jsonのような情報です。
レストランの注文で例えるなら、
テイクアウトです
アレルギーがあります
会員番号はこれです
みたいな注文そのものとは別の付帯情報に近いです。
Content-Type
bodyに入っているデータが何形式なのかを伝えます。
Content-Type: application/jsonなら、
このbodyはJSONです
という意味です。
Authorization
認証情報を送るときによく使われます。
たとえばBearer tokenを使うAPIなら、
Authorization: Bearer TOKENのように送ります。
API側はこれを見て、
誰から来たrequestなのか
この操作を許可していいのか
を判断します。
bodyは「実際に渡したい中身」
POSTやPATCHなどでは、request bodyへデータを入れることがあります。
たとえば新しい記事を作るなら、
{
"title": "APIって結局何?",
"status": "draft"
}のようなJSONを送れます。
JavaScriptなら、
await fetch('/api/articles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'APIって結局何?',
status: 'draft',
}),
})のような形です。
ここで、
API = JSON
ではないことも覚えておきたいです。
HTTPではJSON以外にも、
HTML
plain text
form data
XML
画像などのbinary data
を扱えます。
JSONはWeb APIで非常によく使われるデータ形式ですが、APIそのものではありません。
MDNでも、JSONを使うREST APIの例として Content-Type: application/json が紹介されています。
参考: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Type(外部サイト)
バックエンドではrequestを受けてから何をしている?
フロント側からrequestを送ったあと、バックエンドでは何が起きるのでしょうか。
たとえばLaravelで、
POST /api/articlesを受けたとします。
かなり単純化すると、
routeを見つける
→ requestの値を受け取る
→ validationする
→ 認証・権限を確認する
→ 必要な処理をする
→ DBへ保存する
→ responseを返す
という流れになります。
ここで重要なのは、
APIはDBそのものではない
ということです。
APIの後ろにDBがあることは多いですが、
DBを使わず計算だけする
外部APIを呼ぶ
ファイルを生成する
メールを送信する
Queueへjobを追加する
といった処理もできます。
APIは、
フロントとDBを直結するトンネル
というより、
外部から処理を依頼するためのインターフェイス
です。
responseでは「結果」と「どうなったか」が返ってくる
バックエンドで処理が終わったらresponseを返します。
たとえば記事作成が成功したなら、
HTTP/1.1 201 Created
Content-Type: application/json{
"id": 123,
"title": "APIって結局何?"
}のような形です。
ここで出てくるのがstatus codeです。
HTTPのstatus codeは、requestを処理した結果を3桁の数字で表します。
RFC 9110では、大きく5クラスに分かれます。
1xx = 情報
2xx = 成功
3xx = リダイレクト
4xx = クライアント側のrequestに問題
5xx = サーバー側で処理できなかった
参考: https://www.rfc-editor.org/rfc/rfc9110.html#name-status-codes(外部サイト)
よく見るものなら、
200 OK
request成功。
201 Created
requestによって新しいresourceが作成された。
400 Bad Request
request内容に問題がある。
401 Unauthorized
認証が必要、または認証に問題があるケースで使われます。
403 Forbidden
誰なのかは分かっていても、その操作を許可できない。
404 Not Found
対象resourceが見つからない。
500 Internal Server Error
サーバー側で処理中に問題が起きた。
です。
フロント側はresponseのbodyだけではなく、status codeを見て、
成功画面を出す
入力エラーを表示する
ログイン画面へ戻す
エラー表示をする
などを判断できます。

APIの「認証」と「認可」は何をしてる?
APIで個人情報や更新処理を扱うなら、誰でも好きに呼べてはいけません。
そこで認証があります。
たとえばログイン後にtokenを持ち、
Authorization: Bearer TOKENとしてrequestを送る。
API側でtokenを確認して、
このrequestを送ったのは誰か
を判定します。
これが認証です。
さらに、
このユーザーはこの記事を編集していいのか?
まで確認するのが認可です。
たとえば、
ログインしている = 認証OK
でも、
他人の記事を削除できる = ダメ
です。
APIを作るときは、
endpointを作ってデータが返った!
で終わらず、
誰が呼べるのか
何ができるのか
まで考える必要があります。
REST APIって結局何?
APIの説明を調べると、ほぼ必ずRESTが出てきます。
ただ、
API = REST
ではありません。
RESTはWeb APIを設計する一つのスタイルです。
HTTPのresourceやmethodなどを活かし、
GET /articles
GET /articles/123
POST /articles
PATCH /articles/123
DELETE /articles/123のように、resourceを中心にAPIを設計する形がよく見られます。
一方でAPIには、
GraphQL
RPC系
WebSocketを使う仕組み
ブラウザ内のWeb API
ライブラリが提供するAPI
など、REST以外にもいろいろあります。
初心者のうちは、
APIという大きな概念の中に、HTTPを使うWeb APIがあって、その設計方法の一つとしてRESTがある
くらいで十分だと思います。
フロントからAPIを呼ぶとき、実際には何を渡している?
ここまでを一回つなげます。
たとえばフロントから、
const response = await fetch('/api/articles/123', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer TOKEN',
},
body: JSON.stringify({
title: '更新したタイトル',
}),
})
const data = await response.json()としたとします。
このrequestでは、
endpoint
/api/articles/123method
PATCHheaders
Content-Type: application/json
Authorization: Bearer TOKENbody
{
"title": "更新したタイトル"
}を送っています。
バックエンドはそれを受け取り、
誰から来たか
入力は正しいか
ID 123の記事があるか
この人が変更していいか
DBをどう更新するか
を処理します。
そして、
status code
headers
body
をresponseとして返します。
APIという言葉だけだとぼんやりしますが、実際に飛んでいるものを分解すると、それほど謎ではありません。
DevToolsのNetworkを見るとAPIが急に分かりやすくなる
APIを理解するなら、コードだけを見るよりブラウザのDevToolsにあるNetworkタブを見るのがかなり分かりやすいです。
APIを呼んだあとrequestを開くと、
Request URL
Request Method
Status Code
Request Headers
Response Headers
Payload
Response
などを確認できます。
つまり、この記事で説明してきたものがほぼ全部見えます。
fetchが動かない
ときも、
そもそもrequestは飛んでいる?
URLは合っている?
POSTのつもりがGETになってない?
bodyは入っている?
401なのか500なのか?
responseには何が返っている?
と追えます。
APIを「見えない裏側の何か」ではなく、
requestとresponseとして実際に観察できるもの
にすると、かなり理解しやすくなります。
APIでエラーになったら「どこまで届いたか」を見る
API周りでエラーになると、
API壊れた
でまとめたくなります。
でも実際にはいろいろあります。
request自体が飛んでいない
フロント側のJavaScriptや処理に問題がある。
endpointが違う
404になる。
認証情報がない
401などになる。
権限がない
403などになる。
validationで落ちた
400系や422など、APIの設計に応じたresponseになる。
バックエンド内部で失敗した
500系になることがある。
DBや外部サービスで失敗した
APIまでは届いているけど、その後ろで処理できていない。
なので、
フロント → API → 処理 → DB / 外部サービス → response
のどこまで進んだかを見る。
これは前にNginxを整理したときの、
ブラウザ → Nginx → アプリ
と同じ考え方です。
通信を一本道で見ると、エラーの切り分けもしやすくなります。
APIは「フロントとバックエンドをつなぐもの」だけど、それだけじゃなかった
最初の、
API = フロントとバックエンドでデータをやり取りするもの
という理解は、大きくは間違っていません。
Webアプリでは実際にその使い方をよくします。
ただ、今回整理すると、もう少し正確には、
API = ソフトウェア同士が決められたルールで機能やデータをやり取りするためのインターフェイス
です。
WebのHTTP APIなら、
endpoint = どこへ
method = 何をしてほしい
headers = 補足情報
body = 渡す中身
status code = どうなった
response body = 返ってきた結果
と分解できます。
レストランの例なら、
店を選ぶ
→ 注文窓口を選ぶ
→ 注文内容を伝える
→ 会員情報などを見せる
→ 厨房が処理する
→ 結果が返ってくる
という流れです。
少しふざけた例えですが、実際のHTTPへ戻すと全部対応しています。
APIを勉強するときは、RESTという言葉やstatus codeを一個ずつ暗記するより、
このrequestで、どこに何を渡して、何が返ってきた?
を一回追ってみる。
それだけで、フロントとバックエンドの間で起きていることがかなり見えるようになると思います。


