API
API ・ えーぴーあい
プログラム同士が機能を呼び合うための窓口の約束事。中身を隠し、境界の形だけを契約として公開する。
✦ 30秒で試す — 航海中身を丸ごと作り替えても、使う側は誰も気づかない窓口内部を改修して一覧の順番が変わると、利用者は?予想してみる概要
API は Application Programming Interface の略で、「この形式で頼めば、この形式で返す」というプログラム同士の契約です。人間がボタンや画面(ユーザーインターフェース)を通じてソフトウェアを操作するのに対し、プログラムは API という窓口を通じて別のプログラムの機能を呼び出します。呼び出す側は相手の内部実装を知る必要がなく、公開された「呼び出し方」と「返ってくる形」だけを知っていればよい——この割り切りが API という概念の核心です。
現代の Web 開発の文脈では、API といえば HTTP で JSON をやり取りする Web API を指すことがほとんどです。フロントエンドがバックエンドのサーバからデータを取るのも、自社サービスの機能を外部の開発者に開放するのも、決済や地図のような外部サービスを自分のアプリに組み込むのも、すべて API という語彙の上で行われます。ただし API は Web だけの言葉ではなく、ライブラリの関数も OS の機能呼び出しも、「実装ではなく窓口に依存する」という同じ構造を持っています。
なぜ生まれたか
ソフトウェアが大きくなると、すべてを一枚岩で書くことは不可能になります。あるプログラムが別のプログラムの機能を使いたいとき、相手のソースコードの中身にまで依存してしまうと、相手が内部を少し変えただけでこちらが壊れる、という密結合の地獄に陥ります。そこで「内部は自由に変えてよい。ただし窓口の仕様だけは守る」という境界線を引く発想が生まれました。OS がシステムコールという形でハードウェア操作の窓口を提供したのが古典的な例で、アプリケーションは OS の内部実装を知らずにファイルやネットワークを扱えますし、OS の側はディスクの制御方法を入れ替えてもアプリを作り直させずに済みます。
インターネットの普及は、この考え方を組織の壁を越えたものにしました。2000年代、Amazon や Salesforce、eBay などが自社機能を Web API 経由で外部に開放し、「サービスとサービスをネットワーク越しの契約でつなぐ」スタイルが一般化します。他社のシステムの内部を知らなくても、公開された仕様どおりにリクエストを送れば連携できる——API はこうして、システム間分業の基本単位になりました。
詳細
契約としてのAPI
API の本質は「インターフェース=境界面の取り決め」です。取り決めには、呼び出しの入口(エンドポイントや関数名)、渡すべき入力(パラメータ)、返ってくる出力(レスポンスの形式)、そして失敗したときの振る舞い(エラーの表現)が含まれます。Web API の典型的な一往復はこうなります。
呼び出す側から見えるのはリクエストとレスポンスだけで、サーバの内側で何が起きているか(どんな言語で書かれ、どんなデータベースを使っているか)は完全に隠されています。この隠蔽のおかげで、提供側は契約さえ守れば内部を自由に作り変えられます。境界を1本の線で描くと、次のようになります。
APIの広がりと種類
「API」は Web API だけの言葉ではありません。プログラミング言語の標準ライブラリの関数群も、OS のシステムコールも、ブラウザが JavaScript に提供する DOM API も、すべて API です。共通するのは「実装ではなく窓口に依存する」という構造で、呼び出しが同じプロセスの中の関数呼び出しか、ネットワーク越しの HTTP リクエストかは、契約の中身ではなく運び方の違いにすぎません。
Web API の設計様式にも系譜があります。リソースを URL で表し HTTP メソッドで操作する REST API が事実上の標準となり、その限界への応答として、クライアントが必要なデータの形を指定する GraphQL や、スキーマから型付きのコードを生成してバイナリで高速に呼び合う gRPC が登場しました。どれを選ぶかは、誰が使う API か(社外の不特定多数か、社内のサービス間か)と、性能や型の厳密さへの要求で決まります。
システム設計の構成単位として
API はアーキテクチャを語るときの共通言語でもあります。SPA はフロントエンドとバックエンドを API で分離する構成ですし、マイクロサービスはサービス同士が API だけで会話することを規律とする設計です。逆に言えば、API の境界の引き方を間違えると、サービスを分けたのに互いの内部事情に依存し合い、1つの変更で全サービスを同時にデプロイし直さなければならない「分散モノリス」が生まれます。どこに線を引けば内側の変更が外へ漏れないか——境界設計こそが API 設計の本丸です。
実務での勘所と、契約が守れない理由
API を提供する側に回ると、機能そのものより「契約の維持」に労力を割くことになります。一度公開した API の仕様を変えると利用者のコードが壊れるため、フィールドの追加のような後方互換な変更に留めるか、/v1 /v2 のようなバージョニングで移行期間を設けるのが定石です。仕様は OpenAPI などのスキーマ定義として書き、ドキュメントやクライアントのコードをそこから生成すると、「仕様書と実装が食い違う」事故を減らせます。
ただし、「契約さえ守れば内部を自由に作り変えられる」には裏返しがあります。Google のエンジニア Hyrum Wright の名を取ったハイラムの法則は、「利用者が十分に多ければ、契約に何を書いたかに関係なく、観測できる挙動のすべてに誰かが依存する」と述べます。仕様では順序を保証していない一覧がたまたま id 順に返っていれば、それを前提にしたコードが必ずどこかに生まれます。エラーメッセージの文言を解析する利用者、応答の速さを前提にタイムアウトを短くした利用者もいます。内部のデータベースを入れ替えて並び順が変わった瞬間、契約違反ではないのに誰かが壊れる——境界の線は利用者が増えるほど内側へにじむ、ということです。対策は、保証しない挙動をわざと揺らしておく(順序を明示的にランダムにする、など)、契約に含めるものを明文化する、互換性テストを利用者の使い方に寄せる、といった地道なものです。
外部に開放する API には、誰が呼んでいるかを確かめる認証と、何をしてよいかを決める認可が欠かせません。手軽な API キーから、利用者の代理でアクセスさせる OAuth まで、守りたいものに応じて選びます。さらに、1つの利用者が呼び出しを連打して全体を巻き込まないよう、単位時間あたりの呼び出し回数に上限を設けるレート制限も、公開 API では事実上の必須装備です。
試問
あなたは、多くの会社が使っている Web API(プログラム同士が機能を呼び合う窓口)の提供者です。これから入れたい8つの変更が並んでいます。利用者のプログラムがそのまま動き続ける変更か、どこかの利用者を壊しうる変更かを見分けます。
8つの変更を、利用者を壊さない変更と、壊しうる変更に仕分けよ
項目を選んでから、入れる箱を選びます
