Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQLのあまり知られていない魅力 (スキーマの表現力編) / domain model...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
adwd
February 25, 2022
Programming
6.3k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphQLのあまり知られていない魅力 (スキーマの表現力編) / domain modeling with GraphQL Schema
adwd
February 25, 2022
More Decks by adwd
See All by adwd
RxJSで状態を管理する / state management by RxJS
adwd
1
1.3k
Savkin先生から学んだぼくの考えた最強のAngularアプリアーキテクチャ / The best Angular application architecture
adwd
1
1.2k
create-react-app-introduction
adwd
7
2k
React/Redux Introduction
adwd
17
5.3k
Other Decks in Programming
See All in Programming
AI駆動開発を妨げる技術的負債の解消アプローチ / ai-refactoring-approach
minodriven
17
9.1k
「正の参照」と 「負の導出」で組む ハーネスエンジニアリング
cottpan
1
140
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
490
act2-costs.pdf
sumedhbala
0
110
ルールを書いて終わらせないハーネスエンジニアリング
yug1224
3
1.5k
霧の中の代数的エフェクト
funnyycat
1
400
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
170
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
150
自作OSでスライド発表する
uyuki234
1
3.8k
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
780
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
140
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
0
210
Featured
See All Featured
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
250
A designer walks into a library…
pauljervisheath
211
24k
Code Reviewing Like a Champion
maltzj
528
40k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.8k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
650
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Odyssey Design
rkendrick25
PRO
2
730
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
320
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
2
340
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
630
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Transcript
GraphQLのあまり知られていない魅力 (スキーマの表現力編) ZOZO Tech Talk #4 - Webフロントエンド×新規事業 株式会社ZOZO
計測プラットフォーム本部 計測システム部 西田 雅博 Copyright © ZOZO, Inc.
© ZOZO, Inc. 株式会社ZOZO 計測プラットフォーム本部 計測システム部 西田 雅博 GraphQL+Reactを極めたい Webフロントエンドエンジニア
Rustもやりたい 2
© ZOZO, Inc. 目次 1. GraphQLとは 2. 一般的に知られているGraphQLのメリット 3. たまたま実感した予想外のGraphQLのメリット
4. こんなGraphQLスキーマです 5. GraphQLスキーマの表現力から得られたメリット 6. まとめ 3
© ZOZO, Inc. GraphQLとは 4
© ZOZO, Inc. GraphQLとは 5 • Meta(Facebook)が開発したクライアントが指定 したデータの形でサーバーがレスポンスを返す クエリ言語 •
https://graphql.org/ • https://spec.graphql.org/October2021/
© ZOZO, Inc. 一般的に知られていそうなGraphQLのメリット • 画面に必要なデータを取得するのに1度のリクエストで済む • リクエスト、レスポンスに静的型が付くのでTypeScriptなどとの相性がいい • GraphiQLやApollo
Sandboxといったプレイグラウンドが便利 • Apollo FederationやSchema Stitchingなどマイクロサービスを束ねる仕組みがある ついでにデメリットも • すべてが POST /graphql になるのでキャッシュや監視のやり方が変わる • クライアント、サーバーともに実装が変わったりと学習コストが必要 6
© ZOZO, Inc. たまたま実感した予想外のGraphQLのメリット • ある新規事業の小さいサービスをREST APIからGraphQLに移行しようとしている • それほど複雑なQuery, MutationがないのでGraphQL特有のメリットはあまりなく、練習くらい
になると思っていた ところが、 • GraphQLスキーマの表現力が高く、REST APIでは表現しきれなかったサーバーとクライアン ト間のドメインロジックが表現できた 7 次のスライドからZOZOMAT for Handsというとある小さいサービスと、そのサー ビスのドメインロジックを表現できたGraphQLスキーマを紹介します
© ZOZO, Inc. 8 • 足のサイズを測ってピッタリのサイズの靴を買えるZOZOMATの指輪版
© ZOZO, Inc. 9 • 足のサイズを測ってピッタリのサイズの靴を買えるZOZOMATの指輪版 • マットの上に手をおいて、音声のガイドに従ってスマホのカメラで色んな 方向から手を撮影すると最適な指輪のサイズを出してくれる •
まだ一般リリースしてなくてこっそりやってます
© ZOZO, Inc. ZOZOMAT for Handsの測定はステップや状態が多い ユーザーに色んな角度から手をスマホで撮影してもらう必要 がある 1.
真上から撮影して左右どっちの手か、マットが平たく置い てあるかなどを判定する 2. マットの色に沿っていろんな角度から手を撮影する 3. 最後に真上からもう一度撮影して完了 このステップごとにサーバーと通信していて、クライアントは今 どのステップにいるのか、次はどのステップかを知る必要があ る 10
© ZOZO, Inc. ZOZOMAT for Handsはエラーがたくさんある • 最初の真上から撮影するとき
◦ 人差し指と中指の間隔が開きすぎている ◦ カメラが手に近すぎる • いろんな角度から撮影しているとき ◦ 指定した色の方向から撮影していない ◦ カメラの角度が高すぎる • などなど • それぞれ対応した音声ガイドを再生するのでエラーハン ドリングが重要 11
© ZOZO, Inc. こんなGraphQLスキーマです 12
© ZOZO, Inc. type Mutation { """ TODOを追加します """ addTodo(text:
String!): Todo } type Todo { id: ID! text: String! status: TodoStatus! foo: FooUnion! } union FooUnion = BarType | BazType | QuxType GraphQLスキーマの基本的な読み方 • Mutation: 実行でデータが変化する操作 ◦ RESTでいうとPUT/POST/DELETE ◦ QueryはGET • addTodoミューテーション ◦ NonNullなStringを引数にとって ◦ NullableなTodoを返す • type Todoで型を宣言 ◦ id, text, status, fooフィールドがある ◦ どれもNonNull • statusはTodoStatus enum • FooUnionは3つのうちいずれかになる 13 enum TodoStatus { TODO DONE }
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted どんなGraphQLスキーマになったか ※説明用に簡略化していますが実際のスキーマと基本的には同じです 14
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 15 ダブルクォート3つで囲んだところはdescription コメントのようなものだけどMarkdownも使えるれっきとしたドキュメント GraphQLの型で表現しきれないビジネスロジックは無理せずdescriptionを活用する
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 16 descriptionに書いてあるとおりの処理を行うprocessSessionミューテーション ※GraphQLでファイルアップロードは現状できないので、graphql-multipart-requestを使います
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted processSession ミューテーション 17 processSessionミューテーションの結果はセッションの途中、失敗、完了の3種類
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 18 processSessionミューテーションの結果は セッションの途中、失敗、完了の3種類
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 19 セッションの途中の場合は次の測定の指示 enum CaptureInstruction { TOP BLUE # ... }
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 20 測定ステップ失敗の場合はその理由 enum ProcessSessionFailure { CAMERA_PITCH_TOO_LOW DISTANCE_TOO_CLOSE # ... }
© ZOZO, Inc. union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed |
ProcessSessionCompleted type ProcessSessionProgressed { nextInstruction: CaptureInstruction! } type ProcessSessionFailed { failure: ProcessSessionFailure! } type ProcessSessionCompleted { # このIDで session Query を実行すると測定結果が取得できます。 completedSessionId: ID! } ProcessSessionResult ユニオン 21 測定完了の場合は結果を取得するためのID (結果を出すのに数秒かかるので終わったことだけ通知する)
© ZOZO, Inc. type Mutation { """ processSession 計測ステップを進行します。 sessionIdを指定し、撮影した画像をimageに入れて測定ステップを進めてください。
""" processSession(sessionId: ID!, image: Image!): ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted ここまでのまとめ • processSessionを繰り返し使って計測を進める • processSessionは3パターンの結果を返す • 計測途中、失敗、完了それぞれ次の動作に必要な情報 が入っている 22
© ZOZO, Inc. type Query { """ 計測が完了したセッションを取得します。 """ session(id:
ID!): Session } type Session { id: ID! analysis: SessionAnalysis! } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定結果を取得する session クエリ 23
© ZOZO, Inc. type Query { """ 計測が完了したセッションを取得します。 """ session(id:
ID!): Session } type Session { id: ID! analysis: SessionAnalysis! } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定結果を取得する session クエリ 24 測定の結果が分析途中、分析完了、分析失敗の3パターンにな ることがわかる。 それぞれの型の中身は省略するが、途中なら数秒後クエリを再 実行、完了なら結果を表示、失敗ならエラー表示すれば良いこ とがわかる
© ZOZO, Inc. type Mutation { processSession(sessionId: ID!, image: Image!):
ProcessSessionResult! } union ProcessSessionResult = ProcessSessionProgressed | ProcessSessionFailed | ProcessSessionCompleted type Query { session(id: ID!): Session } union SessionAnalysis = AnalysisInProgress | AnalysisCompleted | AnalysisFailed 測定の一連の流れがスキーマから読み取れる 25
© ZOZO, Inc. GraphQLスキーマの表現力から得ら れたメリット 26
© ZOZO, Inc. ドメインモデリングともいえる議論が活発にできた • 最初はREST APIをそのまま移したようなスキーマだったがGitHubのPR上で100件近いコメン トで盛んな議論ができた🔥 27
© ZOZO, Inc. ドメインモデリングともいえる議論が活発にできた • 最初はREST APIをそのまま移したようなスキーマだったがGitHubのPR上で100件近いコメン トで盛んな議論ができた🔥 • 紹介したスキーマは割とシンプルですが原型はかなり違った
◦ Union、EnumといったGraphQLの型システムの恩恵 ◦ 今回は使ってないですがディレクティブも強力です • 以前のREST APIのときは入社間もないこともあって正直言ってあまりドメインを詳細まで理 解できていなかったが、この議論とGraphQLスキーマからよく理解できた 28
© ZOZO, Inc. DDDのドメインモデリングにも使えるのではないか • 先日読んだDomain Modeling Made Functionalという本はF#の型システムを利用してドメイン モデリングしていた
• GraphQLくらいの型システムでも実現可能と思える • マイクロサービスが境界づけられたコンテキストに該当するならそのコンテキストが外部に提 供する能力を可読性高く表現できる…気がする • GraphiQLやApollo Studioで動作が確認しやすいこと、スキーマのドキュメント性が高いことも ドメインエキスパートにやさしいのでは 29
© ZOZO, Inc. まとめ • 小さなサービスにGraphQLを導入した • 予想していなかった効果として、スキーマの表現力によってドメインに関する議論が盛んに 行えた •
GraphQLおすすめです! 30
None