Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GraphQL導入への技術選定
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
松田
September 25, 2024
Technology
780
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
710
Other Decks in Technology
See All in Technology
AI × アーキテクト 第1・2章|生成AIの課題とアーキテクトの素養
daidaidai
0
180
AI時代のPRレビューにどう向き合うか?
kairim0
1
240
Refining Active Record
shugo
0
160
AI導入は済んだ。次は統制を作り替える番だ_AI×開発組織 Summit 2026
techtekt
PRO
0
320
LambdaWebFunctionsを試してみた / exploring-lambda-web-functions
koukihosaka
1
360
DGX Spark でどこまでハッキングができるのか?
kash1064
3
1.4k
React改造してみた
tsukina_7mochi
0
110
初海外で注意すべきこと12選!!!安全快適なre:invent生活にするために
yuuuuuuu168
1
180
V8のArray.prototype.flatを最大約20倍速くするまでと、巨大OSSへの大規模コミットの道のり
riyaamemiya
0
300
Temporal 最高!でも改めて「日付」について調べたら人類の負債すぎる件
riyaamemiya
0
180
DWH の限界突破! AI エージェント向け爆速リアルタイムデータ基盤 ClickHouse
jozono
1
490
Running Kotlin + Quarkus with Lambda
nealle
1
3.9k
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
400
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
2
360
Abbi's Birthday
coloredviolet
4
10k
The Limits of Empathy - UXLibs8
cassininazir
2
720
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
480
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
360
Large-scale JavaScript Application Architecture
addyosmani
516
110k
The SEO Collaboration Effect
kristinabergwall1
1
590
GitHub's CSS Performance
jonrohan
1033
470k
4 Signs Your Business is Dying
shpigford
187
23k
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. ありがとうございました!