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導入への技術選定
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
松田
September 25, 2024
Technology
720
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphQL導入への技術選定
松田
September 25, 2024
More Decks by 松田
See All by 松田
Jetpack Composeのパフォーマンスの基本
matsudamper
0
690
Other Decks in Technology
See All in Technology
AI駆動開発を通して感じた、 AI時代のデザイナーの役割変化
whisaiyo
3
2k
日本 Fintech 未来予測レポート 2027〜2028年(手動編集版)
8maki
0
2.2k
エラーバジェットのアラートのタイミングを考える.pdf
kairim0
0
140
人材育成分科会.pdf
_awache
2
170
社内 AI エージェント Synapse と セマンティックレイヤーの育て方
hiroakis
3
1.8k
LLMにもCAP定理があるという話
harukasakihara
0
330
小さく始める AI 活用推進 ― 日経電子版 Web チームの事例/nikkei-tech-talk47
nikkei_engineer_recruiting
0
250
Disciplined Vibes: Scaling AI-Assisted Engineering
sheharyar
0
140
中期計画、2回作ってみた ~業務委託と正社員、両方の視点から~
demaecan
1
730
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
2k
FinOps × AIエージェントで実現する コストインシデントの自動調査
oasis1994liveforever
0
130
失敗を経て、Harness Engineering で 大切にしたいことを考える / Learning from Failure: What Matters in Harness Engineering
bitkey
PRO
1
350
Featured
See All Featured
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Being A Developer After 40
akosma
91
590k
Building an army of robots
kneath
306
46k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
The SEO identity crisis: Don't let AI make you average
varn
0
490
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
210
Leo the Paperboy
mayatellez
7
1.8k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
Making Projects Easy
brettharned
120
6.7k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
300
How to Talk to Developers About Accessibility
jct
2
230
Transcript
Copyright ©2024 Retty, Inc. GraphQL導入への技術選定 2024/09/10
Retty株式会社 松田
Copyright ©2024 Retty, Inc. 自己紹介 松田 Retty株式会社 アプリチーム Android/サーバーサイドエンジニア
2 X@matsudamper
Copyright ©2024 Retty, Inc. サービス紹介 3
2022.10 2022.10〜 Retty登壇用テンプレート Retty株式会社 名前なまえ Copyright ©2024 Retty,
Inc. Copyright ©2024 Retty, Inc. Rettyについて 4 iOS Android Web
Copyright ©2024 Retty, Inc. この発表について • 使用している技術、抱えていた課題
• GraphQLを選定した理由 • 実装するにあたってのライブラリの選定理由 • 導入で得られたメリット 5
GraphQLを選定した理由
サービス構成 マイクロサービス群 アプリバックエンド アプリ • Kotlin/JVM • Jersey Android/iOS •
状態管理はRedux • Go Protocol Buffers / gRPC REST API Webチームがメイン アプリチームがたまに触る アプリチームがメイン Webチームは殆ど触らない
GraphQLを選定した理由 アプリバックエンド ↔アプリ間での型定義の問題 • オーバーフェッチを避ける為に複数のユーザー型があった ◦ ユーザー画面に使用するユーザー型 ◦ 店舗画面の投稿一覧に使用するユーザー型 ◦
投稿画面に使用するユーザー型 • クライアントの状態管理の Reduxでの問題 ◦ ローカルで管理する型にマッピングする処理がサーバー定義の型分ある ◦ このReduxのActionではこの値は取得できるんだっけ …?という考慮が発生
GraphQLを選定した理由 コード生成の問題 • iOS ◦ 独自のツールを使用 ◦ サーバーコードをリフレクションして、 Swiftのリクエストコードと、レスポンスの型を作成 ◦
メンテナンスコスト ▪ CocoaPods -> Swift Package Manager対応 ▪ 最近はSwift Concurrencyの対応 • Android ◦ サーバーの定義をコピーしてきて使用 ◦ サーバーとクライアントの定義がずれる
GraphQLを選定した理由 欲しいもの • 1つの要素につき1つの型定義 • 必要な値だけ取得 • クライアントでの状態/キャッシュ管理 • コード生成
GraphQL + Apollo Client
GraphQL実装の技術選定・調査 実装する言語を決める • 今のバックエンドはKotlin。社内の今のバックエンドの標準言語は Go。 ◦ 主にGoを使用しているWebチームはアプリバックエンドはほぼ触らない ◦ KotlinはAndroidでも使用。iOSのSwiftも言語の設計思想は近い →
GoでもKotlinでも良い
GraphQL実装の技術選定・調査 バックエンドを実装する場所を決める • 既存のバックエンドに統合 • 新規にサーバーを立ち上げる 既存のバックエンドに統合する事にした • 新規バックエンドにすると ◦
Goを使用して社内のメイン言語と合わせられる ◦ 既存バックエンドを一気に廃止しきれない ▪ 積極開発されなくなり、開発できる人が減り、メンテナンスが困難になる事が想定される
GraphQL実装の技術選定・調査 graphql.org/community/tools-and-libraries から使えそうなライブラリを探す 選定 • Spring Boot統合はあるがJersey統合は無い ◦ Jersey標準仕様のシンプルな実装なのでそれはそう •
既存の処理にgraphql-java/graphql-javaを乗せる事にした ◦ Spring Boot統合もこれを使用
スキーマファースト vs コードファースト 選定理由 • スキーマをサーバーとクライアントの関心を分ける壁として意識させる • コードの都合がスキーマに漏れ出ないようにする GraphQL実装の技術選定・調査 スキーマファーストを選択
コード生成ライブラリ kobylynskyi/graphql-java-codegenを使用 • Kotlinでの生成に対応したのがこのライブラリくらい • 少しの修正で問題なく使用できた スキーマとコードのマッピング graphql-java-kickstart/graphql-java-toolsを使用 • 生成したコードをGraphQLに簡単にマッピングできる
• 実装漏れを検出でき、実行時エラーを防げる GraphQL実装の技術選定・調査
graphql-java-codegen の修正部分 GraphQL実装の技術選定・調査 restaurant { id: Id reservationAttributes { ~
} } 親に含まれない内部的な 値を渡したい CompletionStage<ReservationAttributes> ↓ CompletionStage<DataFetcherResult<ReservationAttributes>>
スキーマから生成されたコードの管理 理想 ビルド時にスキーマからコードを生成 • 編集不可ファイルを間違って書き換えない 現実 iOSは難しい • ビルド時にコードを生成するのが難しい •
apollo-ios-codegenが生成されたコードを編集して scalar typeのマッピングを行っている GraphQL実装の技術選定・調査
セキュリティ GraphQLは何も対策を行わなければ、クライアントから任意のクエリが発行可能 大きいネストしたリクエストを送って、負荷を掛ける事ができる GraphQL実装の技術選定・調査 restaurant { reports { user {
reports { restaurant { ….
セキュリティ • Query depth & Query complexity ◦ コストを設定し、大きいリクエストを行えないようにすることが可能 ◦
正規のリクエストもコストに気を配ったりしなければならず面倒 • Persisted Queries ◦ 事前にクエリを登録しておき、クエリの hashだけを送ってリクエストする ◦ アプリケーションのリリースビルド時にクエリを CIでAmazon S3に送信し、それをサー バー側で参照 ◦ 外部からアクセスできない開発環境はすべてのクエリを許可している GraphQL実装の技術選定・調査
余談 検討時に認識していなかった • Signed Query ◦ クエリに署名してサーバー側で署名を検証する ◦ Persisted Queriesとの比較
▪ クエリをS3にアップロードする手間が無い ▪ Persisted Queriesはhashだけ送るので、通信量が少ない GraphQL実装の技術選定・調査
セキュリティ • Introspection ◦ スキーマの構造を返す機能 ◦ 開発環境以外では、返さないように設定 • スタックトレース ◦
何も設定しないとエラーをそのままクライアントに返す ◦ 意図せず秘匿情報を返す可能性も ◦ サーバー側でエラーを記録し、必要なものだけクライアントに返す用のレスポンスにマッピングし、 他のエラーは返さないように設定 GraphQL実装の技術選定・調査
監視 監視にDatadogを使用 • graphql-javaはJava8の機能まで対応 ◦ CompletableFuture.CompletedStageに未対応、全てCompletableFuture.supplyAsyncを使用 GraphQL実装の技術選定・調査
監視 リフレクションを使用してInstrumentationでidをトレースに付与 GraphQL実装の技術選定・調査
ついでに • idをLongやString、Int型からUserId等のvalue classにした ◦ 他のIdで他のオブジェクトをリクエストするというのを防げる • offset pagingからcursor pagingにした
◦ パフォーマンスが良い実装をするのに都合が良い GraphQL実装の技術選定・調査
導入の成果
DataLoader • n+1問題が発生しないように、ほぼ全てのデータを DataLoader経由で取得 • 実装はgraphql-java/java-dataloaderを使用 • GraphQLとの統合により、クエリの階層ごとにリクエストがまとめて行われるため、効率よくデータが取 得できる 導入の成果
override fun name( restaurant: QlRestaurant, env: DataFetchingEnvironment ): CompletionStage<DataFetcherResult<String?>> {
/** DataLoaderを呼ぶ ** / } override fun status( restaurant: QlRestaurant, env: DataFetchingEnvironment, ): CompletionStage<DataFetcherResult<QlRestaurantStatus?>> { /** ~ ** / } override fun tel( restaurant: QlRestaurant, env: DataFetchingEnvironment, ): CompletionStage<DataFetcherResult<String?>> { /** ~ ** / } フィールドごとに並列に実行される為、実装を気にせず並列に処理される 例) 導入の成果 restaurant { id: Id name: String status: Status tel: String } GraphQL + DataLoaderで 実行速度が改善
表示速度 • before ◦ 店舗の表示に使用している旧 APIは1秒程かかっていた ◦ 追加で0.1秒程かかる3つのAPIを呼び出し • after
◦ GraphQLに移行後は全て合わせて 400ms程で取得 ◦ 体感できる程早く 導入の成果
まとめ • Rettyアプリでは以下の問題が解決 ◦ コードの自動生成による開発効率化 ◦ クライアントでのキャッシュ ◦ 複雑化した型定義 ◦
表示時間の短縮 チーム構成、技術課題、実装の思想を明確化し、適切な技術選定を 導入の成果
Thank you! Copyright ©2024 Retty, Inc. ありがとうございました!