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
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
GraphQL導入への技術選定
Search
松田
September 25, 2024
Technology
760
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
Screen Lens - 今見てる画面を翻訳する
komagata
0
180
10分で知る最近のOmarchy
komagata
0
180
Bet AI Day 2026丨AIを「使う」から、AIが「働く」へ ― LayerXが進める「組織AI」の社会実装
layerx
PRO
3
2.9k
Bet AI Day 2026丨AIによって本質に戻るシステムリスク管理
layerx
PRO
0
1.3k
リージョンの壁を越える、 ちょっと変わったAWSサービスの話
falken
PRO
1
290
Bet AI Day 2026丨Agentは、「金融」という巨大産業の何を変えられるのか
layerx
PRO
0
1.2k
ASTを使って影響範囲を特定する
nealle
0
130
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
110
2026/09/10 Spring_Bootから_Jakarta_EE_MicroProfileへの移行
megascus
0
270
SQL文一行も書けない人事がCortexもろもろを使って人事業務を楽にしてみる
ponponmikankan
1
190
Driving AI Adoption Using In-House GPUs to Serve Qwen
po3rin
2
470
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
290
Featured
See All Featured
Making Projects Easy
brettharned
120
6.7k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
250
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
210
The agentic SEO stack - context over prompts
schlessera
0
910
Designing for humans not robots
tammielis
254
26k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Scaling GitHub
holman
464
140k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2.8k
Navigating Team Friction
lara
192
16k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Automating Front-end Workflow
addyosmani
1369
210k
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. ありがとうございました!