0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ゼロから実務まで④】REST・gRPC・Connectの技術選定とミドルへのステップアップ

0
Posted at

この記事は、API通信を 基礎知識ゼロから実務で通用するところまで 学ぶシリーズ(全4回)の 第4回 です。同じ「ToDo API」を REST・gRPC・Connect の3方式で作りながら、仕組み・実装・実務での運用を順に解説します。

回 内容 章
第1回 Web通信の基礎とREST 00〜03
第2回 gRPCとProtocol Buffers 04〜06
第3回 Connect 07〜09
第4回 技術選定とミドルへのステップアップ 10〜11・用語集

はじめに

最終回では、ここまで学んだ REST・gRPC・Connect を並べて比較し、技術選定の考え方を整理します。そのうえで、APIを扱うエンジニアがジュニアからミドルに上がるときに求められる視点・演習課題・チェックリストをまとめます。

10 比較と技術選定

3つの方式に優劣はなく、向き不向きがあります。技術選定の場で根拠を持って意見を言えるように整理します。

観点 REST gRPC Connect
設計の単位 リソース(名詞)+HTTPメソッド 関数(RPC) 関数(RPC)
契約(スキーマ) 任意(OpenAPI) 必須(.proto) 必須(.proto)
型の自動生成 OpenAPIがあれば可 可 可(TSの型が特に良い)
データ形式 JSON protobuf バイナリ protobuf バイナリ / JSON
HTTP バージョン 1.1 / 2 / 3 HTTP/2 必須 1.1 / 2(gRPC利用時は2)
ブラウザから そのまま使える プロキシが必要 そのまま使える
curl でのデバッグ 簡単 専用ツールが必要 簡単(JSON時)
ストリーミング SSE / WebSocket で別途 4種すべて 4種(ブラウザはServerまで)
HTTPキャッシュ 得意 使えない GET対応メソッドのみ
エラー表現 HTTPステータス+任意形式 grpc-status(トレーラー) HTTPステータス+定型JSON
エコシステム 最大。誰でも知っている 大きい。多言語対応が成熟 成長中(Go / TS / Swift / Kotlin など)
学習コスト 低い 高め(HTTP/2・運用) 中(protobuf と buf)

選び方の目安

  • REST を選ぶ
    外部に公開するAPI。利用者の技術がバラバラ。CDN キャッシュを最大限使いたい。チームが小さく、まず速く作りたい。
  • gRPC を選ぶ
    多言語のマイクロサービス同士の通信。既に gRPC 基盤(サービスメッシュ等)がある。双方向ストリーミングが中心。
  • Connect を選ぶ
    TypeScript のフロントとバックを型で繋ぎたい。gRPC の利点が欲しいがブラウザ対応やデバッグの手間は避けたい。既存 gRPC と共存させたい。

よくある全体構成

入口ごとに利用者に合った方式を選び、内側は同じ .proto 群で統一する。「全部を1つの方式に揃える」必要はありません。

ミドルへの視点:技術選定を ADR に残す

「なぜ Connect にしたのか」は、半年後に入ったメンバーには分かりません。ADR(Architecture Decision Record)という短い文書に、背景・検討した選択肢・決定・その結果生じるトレードオフを残しましょう。この比較表の観点をそのまま使えます。選ばなかった選択肢と、その理由を書くのがポイントです。

11 ミドルへのステップアップ

ここまでで、3つの方式の仕組みと実装は一通り理解できました。最後に、APIを扱うエンジニアがジュニアからミドルに上がるときに求められる視点を整理します。どれも方式に関係なく通用する考え方です。

ジュニアとミドルの違い

場面 ジュニアの視点 ミドルの視点
API を作る 仕様どおりに動く 失敗したとき・変更するとき・負荷が10倍になったときにどうなるかまで考える
エラー とりあえず 500 を返す 呼び出し側が「リトライすべきか」「ユーザーに何を見せるか」を判断できるコードを返す
変更 フィールド名を直す 既存クライアントへの影響を確認し、段階的に移行する
障害 ログを探し回る リクエストIDとトレースで、どのサービスのどこで遅いかを特定する
技術選定 流行っているものを使う トレードオフを言語化し、ADR に残す
レビュー コードの書き方を見る 契約(スキーマ)・互換性・認可・タイムアウトを見る

身につけるべき5つの柱

1. 契約思考

API はサーバーとクライアントの約束です。スキーマ(OpenAPI / .proto)を唯一の正しい情報源にし、実装はそこから導く。変更は「追加は自由、削除と変更は段階的に」。buf breaking や OpenAPI の差分チェックで機械に守らせる。

2. 障害を前提にした設計

ネットワークは必ず失敗します。タイムアウト(デッドライン)・リトライ(バックオフ付き)・冪等性の3点セットを常に意識しましょう。さらに、呼び出し先が落ちているときに呼び続けないサーキットブレーカーや、重要でない機能を切り離して本体を守るグレースフルデグラデーションも知っておくと設計の幅が広がります。

3. 観測可能性(オブザーバビリティ)

本番で何が起きているかを知る手段です。3本柱を押さえましょう。

  • ログ:JSON 形式の構造化ログにし、リクエストID・ユーザーID・RPC名・所要時間・結果コードを必ず含める。
  • メトリクス:RPC ごとのリクエスト数・エラー率・レイテンシ(p50 / p95 / p99)。「平均」ではなく「遅いほうの5%」を見るのがコツ。
  • トレース:OpenTelemetry で、1つのリクエストが複数のサービスをどう渡り歩いたかを可視化する。インターセプターやミドルウェアで自動計測できる。

4. セキュリティ

入力検証(zod / protovalidate)、認証と認可(特にリソース所有者のチェック)、TLS、秘密情報をログやエラーメッセージに出さない、レート制限。OWASP API Security Top 10 は一度通読しておきましょう。

5. テスト

種類 対象 API での例
単体テスト service 層 HTTP を使わず、業務ロジックだけを検証。一番数が多い。
結合テスト ハンドラー〜DB 実際にサーバーを起動し、クライアントから呼んでステータスやエラーコードを検証。
契約テスト スキーマ buf breaking や OpenAPI の差分チェック。クライアントとの約束が守られているか。

Connect では、テスト用にネットワークを使わずサーバーの実装を直接呼べる createRouterTransport が用意されています。クライアントのテストでサーバーを簡単に差し替えられます。

test/todo.test.ts
import { createClient, createRouterTransport, ConnectError, Code } from "@connectrpc/connect";
import { TodoService } from "../src/gen/todo/v1/todo_pb.js";
import { routes } from "../src/connect-routes.js";
import { test } from "node:test";
import assert from "node:assert/strict";

test("存在しない ToDo は NotFound になる", async () => {
  const client = createClient(TodoService, createRouterTransport(routes)); // メモリ内で完結
  await assert.rejects(
    client.getTodo({ id: "nope" }),
    (e) => ConnectError.from(e).code === Code.NotFound,
  );
});

演習課題

読んだだけでは身につきません。次の課題を順にやってみてください。後ろほどミドル寄りです。

  1. REST にページングを足す
    02章の GET /todos にカーソル方式のページングを実装する。limit の上限(例:100)も設ける。
  2. 冪等キーを実装する
    POST /todos で Idempotency-Key ヘッダーを受け取り、同じキーなら前回の結果を返す。
  3. .proto を拡張する
    UpdateTodo と DeleteTodo を追加する。部分更新のために optional やフィールドマスクをどう使うか調べて決める。buf lint を通すこと。
  4. 互換性を壊してみる
    わざと Todo の done を削除し、buf breaking がどう検出するか確認する。次に reserved を使って正しく削除する。
  5. REST と Connect を同居させる
    02章の REST と 08章の Connect が、共通の service 層を呼ぶように書き換える。エラー変換関数を2つ(REST 用・Connect 用)作る。
  6. 観測可能性を入れる
    インターセプターで構造化ログ(JSON)を出し、全ログにリクエストIDを含める。余力があれば OpenTelemetry でトレースを取る。
  7. ADR を書く
    「自分のチームの新規プロジェクトで REST と Connect のどちらを採用するか」を ADR 形式で1ページにまとめる。

自己チェックリスト

全部に自信を持ってチェックできたら、API 設計の議論でミドルとして発言できる状態です。

  • HTTP リクエスト/レスポンスの生テキストを読んで、何が起きているか説明できる
  • 安全・冪等の違いと、それがリトライ設計にどう関係するか説明できる
  • 4xx と 5xx、gRPC の各コードを適切に使い分けられる
  • protobuf のフィールド番号の役割と、互換性を守るルールを説明できる
  • gRPC がブラウザで使えない理由と、Connect がそれをどう解決したか説明できる
  • 全ての外部呼び出しにタイムアウトを設定する習慣がある
  • 認可(リソース所有者チェック)をレビューで確認できる
  • スキーマの変更が既存クライアントに与える影響を判断できる
  • 業務ロジックを通信方式から分離した構成で実装できる
  • REST / gRPC / Connect の選定理由をトレードオフ込みで説明できる

次に読むもの

用語集

用語 意味
API プログラム同士がやりとりするための窓口と約束事。
リソース REST で操作の対象となる「モノ」。URL で指し示す。
エンドポイント API の個々の入口。GET /todos や TodoService/GetTodo。
ステータスコード HTTP レスポンスの結果を表す3桁の数字。
冪等性 何回実行しても結果が同じになる性質。リトライの安全性に関わる。
シリアライズ プログラム内のデータを JSON やバイナリなど送れる形に変換すること。
HTTP/2 1本の接続で複数のやりとりを同時に行える(多重化)、バイナリ形式の HTTP。
トレーラー ボディの後ろに送られるヘッダー。gRPC は結果をここに入れる。
RPC Remote Procedure Call。遠くの関数を手元の関数のように呼ぶ考え方。
Protocol Buffers Google が作ったスキーマ言語兼バイナリ形式。.proto ファイルに書く。
フィールド番号 protobuf で各フィールドを識別する番号。通信ではこれが送られる。変更禁止。
コード生成 スキーマから各言語の型やクライアントを自動で作ること。
ストリーミング 1回の呼び出しで複数のメッセージを連続して送受信すること。
デッドライン 「この時刻までに返して」という締め切り。gRPC / Connect のタイムアウト。
メタデータ gRPC における HTTP ヘッダーのこと。認証情報などを載せる。
インターセプター 全ての RPC に共通する処理を挟み込む仕組み。ミドルウェアに相当。
トランスポート Connect で「どのプロトコルでどこへ送るか」を表す部品。差し替えるだけで方式が変わる。
gRPC-Web ブラウザ向けに gRPC を改変したプロトコル。
Buf / buf CLI .proto の lint・互換性チェック・コード生成を行うツール。
BSR Buf Schema Registry。.proto を公開・共有するレジストリ。
OpenAPI REST API の仕様を YAML / JSON で書く標準形式。
CORS ブラウザが別オリジンの API を呼ぶときの許可の仕組み。
L4 / L7 LB 接続単位で振り分けるか、リクエスト単位で振り分けるかの違い。gRPC には L7 が必要。
ADR Architecture Decision Record。技術的な決定とその理由を残す短い文書。
OpenTelemetry ログ・メトリクス・トレースを収集する標準仕様とツール群。

コード例は connect-es v2 / @grpc/grpc-js / Express 5 / zod を前提にしています。ライブラリのメジャーバージョンが変わると API が変わることがあるので、実装時は公式ドキュメントも併せて確認してください。


ここまで読んでいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?