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
松田
September 25, 2024
Technology
730
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
700
Other Decks in Technology
See All in Technology
Keeping applications secure by evolving OAuth 2.0 and OpenID Connect
ahus1
PRO
1
140
5分でわかるDuckDB Quack
chanyou0311
4
310
10x Speed With QA Agent Platform - How we scaled adoption from individual effort to organizational capability
lycorptech_jp
PRO
0
130
AIに障害切り分けを全部やってもらった。 。 。 。
estie
0
360
事業価値を⽣み出すSREへ SREが担うべき意思決定の5層
kenta_hi
0
180
なぜ人は自分のプロジェクトを 「なんちゃってアジャイル」と 自嘲するのか
kozotaira
0
250
スタートアップにおけるアジャイルの実践について #shibuyagile
murabayashi
3
2.1k
AI駆動開発におけるQAエンジニアの役割事例 〜AI駆動開発の現場から〜
kobayashiyorimitsu
0
310
証券システムを10年Scalaで作り続けるということ - 関数型まつり2026
krrrr38
1
380
小さいから、全部わかる。— 常駐AI "xangi" のすすめ
sugupoko
0
260
インフラ寄りSREでも 開発に踏み出せる〜境界を越えてユーザー体験に向き合いたい〜
sansantech
PRO
0
510
GuardrailからGovernanceへ~AIエージェント運用の次の課題~
sbspsy
1
130
Featured
See All Featured
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
Raft: Consensus for Rubyists
vanstee
141
7.6k
Designing Experiences People Love
moore
143
24k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Scaling GitHub
holman
464
140k
The Cost Of JavaScript in 2023
addyosmani
55
10k
A Tale of Four Properties
chriscoyier
163
24k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
220
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. ありがとうございました!