4.2K Views
February 05, 24
スライド概要
インターフェース定義言語(IDL)に注目しながらREST, GraphQL, gRPCの基本を学ぼう!
「楽しく楽にcoolにsmartに」を理想とするprogrammer/philosopher/liberalist/realist。 好きな言語はClojure, Haskell, Python, English, français, русский。 読書、プログラミング、語学、法学、数学が大好き! イルカと海も大好き🐬
インターフェース定義言語から学ぶ モダンなWeb API方式 REST, GraphQL, gRPC 1
🐬カマイルカ lagénorhynque (defprofile lagénorhynque :id @lagenorhynque :reading "/laʒenɔʁɛ̃k/" :aliases [" " " "] :languages [Java Clojure Haskell Python English français русский] :interests [ / / / ] :job-roles [ ] :motto " " カマイルカ 🐬 日本語 プログラミング 語学 言語学 数学 法 政治 財務 会計 エンジニアリングマネージャー ソフトウェアアーキテクト 楽しく楽にクールにスマートに 2
私の仙台との接点 仙台のイベント「タガヤス」ということで) 🐬は岐阜出身、千葉在住 2016年4月から株式会社オプト(本社: 東京・市ヶ谷) 所属 2017年からオプトの「仙台ラボラトリ」メンバー と合同で仕事することが増えた 2018年春、2023年春には仙台に出張する機会も ( 3
記事: サービス間連携のためのGraphQL APIをClojure で開発している話 4
発表: JavaからScala、そしてClojureへ: 実務で活きる 関数型プログラミング at 【タガヤス その26】初心者歓迎!関数型プログラ ミングって何だろう?(2022-06-24) 5
Table of Contents のスキーマ駆動開発 現代の主要な 方式 の 1. Web API 2. Web API 3. REST/GraphQL/gRPC IDL 6
のスキーマ駆動開発 1. Web API 7
スキーマ駆動開発(schema-driven development) Web APIのサーバとクライアントの間の「契約」で あるスキーマ(schema)を先行して定義し、それを 起点に実装を進める開発スタイル スキーマはインターフェース定義言語(inteface definition/description language; IDL)で記述する 認識齟齬/不整合を避けて効率的に開発できる コード/ドキュメント生成などの応用もしやすい a.k.a. スキーマファースト開発(schema-first development) 8
スキーマ駆動開発(サーバサイド)の基本的な流れ 1. APIの構想/方式設計 2. APIスキーマの(初期)設計 アウトプット: IDLファイル 3. [optional] プロジェクト/コードの自動生成 アウトプット: プロジェクトテンプレート/スタ ブ/型定義コード 利用言語/ライブラリ/ツールに大きく依存する 4. APIサーバ実装/テスト ↺ APIスキーマの拡張/修正 9
2. 現代の主要なWeb API方式 REST, GraphQL, gRPC 10
schema definition data format notes REST OpenAPI Specification JSON (text), etc. Swagger (tools) GraphQL GraphQL SDL JSON (text), etc. query language gRPC Protocol Buffers (IDL) Protocol Buffer wire format (binary) protoc (compiler) HTTP/2 11
REST (representational state transfer) 本質: HTTPプロトコルに寄り添ったWeb APIの設計 パターン 具体的な形式は設計者によって揺れが大きい: Richardson Maturity Model OpenAPI Specificationに基づいてYAML/JSON形式 でスキーマを記述できる(de facto standard?) Swagger/OpenAPIの各種ツールでスキーマ編集/ 閲覧や動作確認、コード生成などができる e.g. Swagger Editor (ブラウザ版) 12
13
GraphQL 本質: クライアントに自由度を与えるWebサービス のクエリ言語 cf. RDBに対するSQL (単純なREST APIで発生しやすい)オーバーフェッ チング/アンダーフェッチングを回避できる GraphQL Schema Definition Language (SDL)でス キーマを記述する GraphiQLというブラウザIDEでAPIコールを試す ことができる e.g. GitHub GraphQL APIのExplorer クライアントはGraphQLのクエリ言語を用いて必 要最小限のデータのみを選択的に取得できる 14
15
gRPC 本質: HTTP/2ベースの効率的なRPC (remote procedure call)のためのフレームワーク マイクロサービスアーキテクチャのバックエンド サービス間連携で有力な選択肢 Webフロントエンド向けのAPIとしても利用でき る: grpc-web Protocol BuffersのIDLでスキーマを記述する protoc (Protocol Buffers compiler)でサーバ/ク ライアントのコード生成ができる Protocol Buffer wire format (バイナリ形式)でデー タを送受信する 16
17
の 3. REST/GraphQL/gRPC IDL 18
インターフェース定義言語(IDL)の記述 API style REST GraphQL gRPC IDL OpenAPI Specification (.yaml, .json) GraphQL SDL (.graphql) Protocol Buffers (.proto) 19
題材: 蔵書/読書管理サービス cf. ブクログ, 読書メーター 主な機能 カタログの書籍情報のCRUD 本棚(蔵書)の書籍の読書状況/レビュー情報の CRUD ※ サンプルコード: web-api-style-comparison 20
[REST] データモデル(エンティティ)の定義例 components: schemas: Book: title: Book type: object properties: id: type: integer description: ID minimum: 0 readOnly: true title: type: string description: # ...( )... 書籍 以下略 書名 components > schemas > Book: Book のJSON仕様(cf. JSON Schema) データ 21
required: - id - title - author # ...( )... description: example: id: 1 title: Web API author: '( ) Arnaud Lauret, ( ) , ( ) ' publisher: publication_date: '2020-08-26' official_site_url: 'https://www.shoeisha.co.jp/book/ detail/9784798167015' 以下略 書籍 の設計 著 修 株式会社クイープ 翔泳社 翻訳 株式会社クイープ 監 必須のプロパティ データ例 required: example: 22
[REST] 参照系操作の定義例 paths: /books: get: tags: - book_catalog summary: operationId: get-books description: 書籍の一覧取得 検索条件を満たす書籍をカタログから取得する。 paths > /books > get: リクエスト GET パス /books に対する 23
parameters: - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/page' - schema: type: string minLength: 1 in: query name: title description: ( ) - schema: type: string minLength: 1 in: query # ...( )... 書名 部分一致 以下略 parameters: パラメータの仕様 24
responses: '200': description: OK content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Book' pagination: $ref: '#/components/schemas/Pagination' # ...( )... 以下略 レスポンスステータスコー ド200の場合 content > application/json: レスポンス ボディのJSON仕様 responses > '200': 25
[REST] 更新系操作の定義例 paths: /books: post: tags: - book_catalog summary: operationId: post-books description: 書籍の追加 書籍をカタログに追加する。 paths > /books > post: るPOSTリクエスト パス /books に対す 26
requestBody: content: application/json: schema: $ref: '#/components/schemas/Book' examples: example-1: value: title: Web API author: '( ) Arnaud Lauret, ( , ( ) ' publisher: publication_date: '2020-08-26' # ...( )... description: の設計 著 クイープ 監修 株式会社クイープ 翔泳社 以下略 書籍 翻訳) 株式会社 requestBody > content > application/json: 様 リクエストボディのJSON仕 27
responses: '201': description: Created headers: Location: schema: type: string format: uri-reference example: /books/1 description: 追加された書籍へのURL レスポンスステータスコー ド201の場合 headers > Location: レスポンスのLocation ヘッダーの仕様 responses > '201': 28
[GraphQL]
データモデル(エンティティ)の定義例
書籍
書籍
書名
著者
出版社
出版年月日
中略
レビューの集計結果
"""
"""
type Book {
"""
ID"""
id: ID!
"""
"""
title: String!
"""
"""
author: String!
"""
"""
publisher: String!
"""
"""
# ...(
)...
"""
"""
reviewSummary: ReviewSummary!
}
データのオブジェクト型定義
T! はNon-Null型(ただの T はnullable型)
Book
29
レビューの集計結果 平均ランク リスト """ """ type ReviewSummary { """ """ averageRank: Float """ """ reviews: [Review!]! } """ """ type Review { """ ( 1 5)""" rank: Int """ """ comment: String } レビュー ランク 星の数 〜 コメント データのオブジェクト型 定義 [T] はList型([T!], [T]!, [T!]! もある) ReviewSummary, Review 30
[GraphQL] 参照系操作の定義例 type Query { """ """ booksInCatalog( """ ( )""" title: String """ ( )""" author: String """ ( )""" publisher: String """ ( )""" publishedOnFrom: Date """ ( )""" publishedOnTo: Date ): [Book!]! } カタログの書籍の一覧取得 書名 部分一致 著者 部分一致 出版社 部分一致 出版年月日 始点 出版年月日 終点 クエリ(Query型フィールド)の定義 booksInCatalog 31
[GraphQL] 更新系操作の定義例 type Mutation { """ """ addBookToCatalog( """ """ input: AddBookToCatalogInput! ): AddBookToCatalogPayload } カタログへの書籍の追加 追加内容 ミューテーション(Mutation型 addBookToCatalog ) フィールド の定義 32
input AddBookToCatalogInput { """ """ title: String! """ """ author: String! """ """ publisher: String! """ """ # ...( )... } type AddBookToCatalogPayload { """ """ book: Book! } 書名 著者 出版社 出版年月日 以下略 追加された書籍 ミューテーション用の入出力の 型定義 入力の型は input 、出力の型は type で定義す る addBookToCatalog 33
[gRPC] データモデル(エンティティ)の定義例 書籍 書籍 書名 著者 出版社 出版年月日 中略 レビューの集計結果 // message Book { // ID int32 id = 1; // string title = 2; // string author = 3; // string publisher = 4; // /* ...( )... */ // ReviewSummary review_summary = 9; } データのメッセージ型定義 = の右辺のフィールド番号でフィールドが識別さ れる(ユニークに保ち、再利用しない) Book 34
レビューの集計結果 平均ランク リスト // message ReviewSummary { // optional float average_rank = 1; // repeated Review reviews = 2; } // message Review { // ( 1 5) optional int32 rank = 1; // optional string comment = 2; } レビュー ランク 星の数 〜 コメント データのメッセージ型定 義 optional は省略可能フィールド repeated は0個以上の繰り返しフィールド ReviewSummary, Review 35
[gRPC] 書籍管理サービス 書籍を一覧取得する 参照系操作の定義例 の // "Biblog" gRPC API service BiblogApi { // rpc ListBooksInCatalog(ListBooksInCatalogRequest) returns ( ListBooksInCatalogResponse); } サービスのListBooksInCatalogメソッド BiblogApi の定義 36
message ListBooksInCatalogRequest { // ( ) optional string title = 1; // ( ) optional string author = 2; // ( ) optional string publisher = 3; // ( ) /* ...( )... */ } message ListBooksInCatalogResponse { // repeated Book books = 1; } 書名 部分一致 著者 部分一致 出版社 部分一致 出版年月日 始点 以下略 書籍のリスト ListBooksInCatalog メソッド用の入出力の型定義 37
[gRPC] 書籍管理サービス 書籍を追加する 更新系操作の定義例 の // "Biblog" gRPC API service BiblogApi { // rpc AddBookToCatalog(AddBookToCatalogRequest) returns (AddB ookToCatalogResponse); } サービスのAddBookToCatalogメソッド BiblogApi の定義 38
message AddBookToCatalogRequest { // string title = 1; // string author = 2; // string publisher = 3; // /* ...( )... */ } message AddBookToCatalogResponse { // Book book = 1; } 書名 著者 出版社 出版年月日 以下略 追加された書籍 AddBookToCatalog メソッド用の入出力の型定義 39
時代のWebサービスのインターフェース(API) REST以外の方式も選択肢として検討しよう スキーマ駆動開発を実践しよう 内部実装だけでなく設計について学ぼう XaaS 40
Further Reading 公式ドキュメント OpenAPI Initiative Getting Started | OpenAPI Documentation GraphQL | A query language for your API Introduction to GraphQL | GraphQL gRPC Introduction to gRPC | gRPC Overview | Protocol Buffers Documentation 41
とその設計 (REST) API 『Web APIの設計』 『Web API: The Good Parts』 『Webを支える技術 ―― HTTP,URI,HTML,そ してREST』 『APIデザイン・パターン』 42
GraphQL, gRPC 『初めてのGraphQL ――Webサービスを作って学 ぶ新世代API』 GraphQL in Action How to GraphQL - The Fullstack Tutorial for GraphQL gRPC: Up and Running API : gRPC OpenAPI REST | Google Cloud 設計 、 、 の概要と、それ らを使用するタイミングを理解する 公式ブログ 43
サンプルコード lagenorhynque/web-api-style-comparison lagenorhynque/clj-rest-api: REST API (Clojure) cf. 3 Lisp 3 ( ) lagenorhynque/aqoursql: GraphQL API (Clojure) cf. Clojure Lacinia GraphQL API lagenorhynque/route-guide: gRPC API (Clojure) cf. Clojure Protojure gRPC API 『 つの の の つの世界』 電子版 で 開発してみた で 開発してみた 44