BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース AirbnbにおけるGraphQLマイグレーション

AirbnbにおけるGraphQLマイグレーション

原文(投稿日:2019/12/03)へのリンク

Airbnbは、APIの大半をGraphQLに移行して、ページロード時間の短縮とより直感的なユーザエクスペリエンスを実現することに成功した。GraphQL Summitで行われたプレゼンテーションでは、Brie Bunge氏が、同社の多くのチームで使用されたマルチステージのマイグレーションプロセスについて説明した。 

各ステージを成功させることによってAirbnbでは、100パーセント型安全でオーバーフェッチングのないApolloおよびGraphQLアプリを完成すると同時に、マイグレーション作業の各過程を通じてサイトの稼働と運用を維持することにも成功した。ApolloとGraphQLの適用によって、従来のRESTベースのアーキテクチャでは到底実現できなかったような、新たなパフォーマンス改善を実現するための基礎を作り上げたのだ。

マイグレーション作業に着手するにあたって同社では、対処すべき前提条件が2つあった。ひとつは、GraphQLをバックエンドにセットアップすることだ。Adam Neary氏が、AirbnbにおけるGraphQLの立ち上げについて記している。 

ふたつめの前提条件は、フロントエンドにTypeScriptを導入することだ。TypeScriptとその型安全性の導入によって開発速度が向上し、開発成果に対してチームがより自信を持てるようになった。TypeScriptの型定義はスキーマから(apollo client:codegen --target=typescriptを使用して)直接生成することが可能である。生成された型は、バックエンドとフロントエンドで共通的に使用される。

TypeScriptはAirbnbにおけるフロントエンド開発の公式言語になっており、300万におよぶ同社のコードベースの半分がTypeScriptに移行している。Bunge氏は以前のJSConfで、AirbnbにおけるTypeScriptの採用に関して講演を行った。

GraphQLへの変換にはおもに3つの選択肢がある、と氏は言う。ひとつめの、最も魅力的な選択は、すべてをスクラッチから書き直すことだ。メジャーなプロジェクトの一としてはこのようなケースもあるが、必ずしも可能な選択肢であるとは限らない。ふたつめの、システムを停止してリファクタするという選択肢は、小規模ないし独立したチームでは成り立つが、大勢が共同で開発を行う場合には難しい。

Airbnbが推奨するのはインクリメンタルな適用方法だ。特に大規模なチームや大規模な既存コードベースでは、これが最も安全かつ現実的なアプローチとなる。Bunge氏が説明したプロセスは5つのステージで構成されていて、それぞれのステージの成果物は、運用提供が可能であり、機能的に完成した、リグレッションのないアプリケーションのバージョンとなっている。

最初のステージではデータの提供元を変更し、その使用方法には手を加えない。GraphQLエンドポイントとTypeScriptを配置することにより、REST要求をGraphQLの要求に置き換えることを可能にする。この最初のステージの目標は、フロントエンドとバックエンドのインテグレーションと、TypeScript型生成が適切に動作することの確認にある。ReactコンポーネントやAPI応答の形式には手を加えない。これには、RESTエンドポイントにマッチしたGraphQLクエリとミューテーション(mutation)が必要になる。 

この初期段階でAirbnbが活用したGraphQLの機能は、エイリアスとアダプタの2つだった。エイリアス(aliasing)は、GraphQLから返されるキャメルケース(camel-case)のプロパティと、古いRESTエンドポイントのスネークケース(snake-case)のプロパティとのマッピングを可能にする。アダプタは、GraphQLのレスポンスを変換してRESTの応答と再帰的に比較可能にすることで、GraphQLが以前と同じデータを返していることを保証するために使用する。これらのアダプタは後に排除されたが、最初のステージにおいて同一性の目標を達成する上で、非常に重要な役割を果たした。

第2ステージでは、以降のステージにおける信頼性を向上するため、コード全体の型の伝搬に重点が置かれた。この時点では、ランタイムの動作に影響があってはならない。

第3ステージでは、Apolloの使用方法が改善された。これまでのステージではApollo Clientを直接使用して、Redux Actionを起動し、コンポーネントではReduxストアを使用していた。React Hooks(@apollo/react-hooks)を使ったリファクタリングによって、Reduxストアの代わりにApolloキャッシュ使用できるようになる。 

GraphQLの大きな利点は、オーバーフェッチングの減少だ。大規模なクエリ(メガクエリ)を持った第1ステージでは、旧RESTエンドポイントのオーバーフェッチングにはまったく手が付けられていなかったが、第4ステージでは、より詳細なクエリフラグメントを導入することにより、この問題への対処を可能にする。

まず最初に、GraphSQLについて知るのはアプリのルートのみになり、ツリー内の全コンポーネントが必要とするデータのすべてをフェッチしなければならない。改善プロセスはコンポーネントツリーの最末端のノードに始まり、サブコンポーネントの必要とするデータのみのGraphQLクエリを生成するようになる。TypeScriptを使うことで、必要なフィールドが存在しなければコンパイラが警告を出してくれる。次に親コンポーネントを、子コンポーネントのフラグメントに基づいたデータをフェッチするように修正する。リーフノード全体で"繰り返し洗い(rinse-and-repeat)"プロセスが実行されると、それが順にルートアプリまで行われる。この方法で、それまで実行されていたメガクエリが、フラグメントの組み合わせ全体によってリプレースされるのだ。各フラグメントは必要なデータのみを要求するので、オーバーフェッチングは減少する。

第5の最終ステージはステージ管理に関するものだ。すべてのコンポーネントがApolloに移行すれば、APIデータとReactのローカルステータス、あるいはクライアントデータのコンテキストにApolloを活用できるようになる。これにより、クライアントデータを処理するための一貫したメンタルモデルが確立し、ReactとApollo、Reduxの要素を組み合わせたフラグメントモデルが改善される。Reduxで必要だった大量のボイラプレートコードも削減され、さらには手盛りソリューションよりも効果的なキャッシュで処理できるようになる。

GraphQLを導入したことでAitrbnbは、新たなチャンスを経験することになった。まずBunge氏があげたシチュエーションは、サービスワーカクエリのプレフェッチングである。GraphQLを可能な限り早くキックオフすることで、ユーザページに表示するデータのレンダリングが高速になる。

サービスワーカがなければ、ページはサーバサイドでレンダリングされるため、ユーザは配信されたページ全体のレンダリングが完了するまで待たされることになる。サービスワーカによってアプリケーションシェルが瞬時に表示されるようになり、データの返送に従ってページが埋められるローディングステージが実現する。JavaScriptの多くはキャッシュされるので、ページのロード自体も高速になる。サービスワーカは、コンポーネントレベルのクエリをルートレベルクエリに切り替えることによる改善も提供する。デバイスの持つ制限によっては、この機能により、ページが完全に対話可能になるまでのトータル時間を、さらに20~50パーセント削減することが可能になる。 

データ重視の統合スキーマも、現在のプロジェクトが追求しているもののひとつだ。現行のスキーマは、Airbnbのサービス指向アーキテクチャに沿ったものとなっているが、サービスが基盤となるデータと組み合わせられる方法がさまざまであるため、データの重複が少なくない。データ中心のスキーマに移行して、アーキテクチャにデータ水和層(hydration layer)を加えることで、重複するデータリクエストの回避と重複するコードの排除が可能になるため、レスポンスの効率向上とキャッシュの改善が期待できる。この開発は現在ベータ段階だが、結果は良好であるため、まもなく発表されるものと思われる。

この記事に星をつける

おすすめ度
スタイル

BT