API設計が楽でコア業務に集中できるように。GraphQLで開発がどう変わったか?タクシーアプリGOの中の人に聞きました【技術選定の裏側:GraphQL編 vol.1】
モダンな技術の活用法に迫る、エンジニア座談会企画がスタート!第1弾はFacebookが開発しているクエリ言語「GraphQL」の魅力に迫ります。
今回は「移動で人を幸せに。」をミッションに掲げ、モビリティ産業のアップデートに挑戦している株式会社Mobility Technologiesより、タクシーアプリ「GO」の法人向けサービス「GO BUSINESS」の開発を担当しているSREのYさんとフロントエンドエンジニアのSさんをお招きし、GraphQLを採用した理由や魅力、苦労した点についてお伺いしました。
■登場人物プロフィール
株式会社Mobility Technologies SREグループ グループマネージャー Y.M
インフラの設計や構築、運用周りを担当しているほか、全体のアーキテクチャ設計やレビューにも関わるなど、幅広く携わっている。
株式会社Mobility Technologies ソフトウェア開発部 S.H
Webのフロントエンド開発を担当。タクシー事業者向けの管理画面の開発を手がけている。
管理画面の開発でGraphQLを採用。開発言語はGoとTypeScript
──お二人が担当されているGO BUSINESSのサービス内容をお聞かせください
Y.M(以下:Y):タクシーアプリ・GOの法人向けサービスですね。請求書払いができるので、経費精算の手間を削減できる点がポイントです。
──それは便利ですね!GraphQLはどのような部分で使われているのですか?
Y:タクシー事業者様向けの管理画面です。アーキテクチャとしては、フロントエンドはSPA構成となっており、裏側にGraphQLを使ったAPIサーバーがあります。さらにその後ろにgRPCサーバーがあり、データをAPIとして抽象化した形で複数のサービスに提供するといった3階層の構造にしています。GraphQLのAPIはBFFのようなイメージで、管理画面のコンテキストに合わせたAPIを提供するためのサービスですね。
ちなみにバックエンドはGo言語で開発していて、GraphQLのライブラリにはgqlgenを使っています。
──フロントエンドの言語も教えていただけますか。
S.H(以下:S):言語はTypeScriptで、GraphQLのAPIを叩くために、ReactにApollo Clientを組み込んで開発しています。
▲取材はオンラインで実施しました
GraphQLで作業効率がアップ。バックエンド、フロントエンドの双方にメリットあり
──GraphQLを採用された理由をお聞かせいただけますか。
Y:GraphQLの導入は、社内でいうと今回で3例目なんですよ。GraphQLに対する知見が蓄えられていて、導入のハードルがなかったのが大きな理由ですね。
──なるほど。フロントエンド側では、導入の懸念はなかったですか?
S:特にはなかったです。別のプロダクト開発でGraphQLを初めて使った時は試行錯誤していたのですが、GO BUSINESSではとてもスムーズに使うことが出来ていますね。
──GraphQLを導入して良かった点は、どういうところですか?
Y:バックエンドとしては、APIの設計がやりやすくなるのは嬉しいですね。GraphQLと比較してRESTが候補にあがることが多いと思うのですが、後者では厳密にやろうとすると一つのAPIリソースしか返さないし、エラーレスポンスの形式などAPI全体の基盤となる設計も一から考える必要があります。GraphQLならAPIの設計は仕様である程度決まっており、ネストするリソースも自然に作れます。また型定義ができることでドキュメントの自動生成も可能になるため、別チームとのAPI仕様に関するやり取りが減り、コア業務に集中できるようになったのも嬉しいポイントですね。
S:以前はAPI仕様が変更になるたびに自らSpecを確認しにいき何かあればチャットで都度やりとりしていたのですが、GraphQLと併用しているApollo Clientやその周辺ライブラリはスキーマの自動取得機能が整っているのでその必要がなくなりましたよね。また、コマンドを叩けば型定義やカスタムフックを自動生成するので人力でやる作業がかなり減りました。
──お互いに嬉しい効果があったんですね。gqlgenやApollo Clientについては、実際に使ってみていかがですか?
Y:gqlgenはGraphQLを実装する上で使える機能が一通り揃っていて、スキーマからのコード生成もできます。APIの口を作るところに関しては、ビジネスロジックの実装だけをやればいいので、とても効率が良いです。
S:以前は状態管理をReduxやカスタムフックで行い、ストアの設計や正規化を自らやっていたのですが、Apollo Clientの場合はレスポンスを正規化してキャッシュの中に保存してくれるので、その辺りのコード量が減りました。機能が増えるとストアも肥大化して設計が難しくなると思うのですが、今のところそのような心配はありません。
▲Mobility Technologies社のMTGの様子(現在は全社員リモートワークも可能)
監視がしづらい、無秩序なコードになってしまうなど…。便利な一方で感じる課題とは
──GraphQLで苦労したことや、課題だと感じることはありますか?
Y:インフラ観点でいうと、監視がしづらいのは大きな課題だと考えています。GraphQLは一つのAPIのポイントだけを提供していて、ステータスを全て200で返すのが原則になっているんです。インフラ側の監視ツールは、基本的にhttpのステータスコードをみて監視することが多いので、アプリケーションレベルでのエラーについては、インフラ監視ではわからない。
対策として、Sentryで例外をキャッチして監視していますが、インフラ側でアラートをかけてエラーが何件起きているのか見るといったことができなくなるので、悩ましいところです。パフォーマンスの監視も同様の理由で難しい。GraphQL Rubyなど一部のライブラリではエージェントと連携してNewRelicやDatadogにGraphQLのメトリクスを送信することは可能ですが汎用的な手法はまだ無いように思います。
S:フロントエンド側ではGraphQLそのものではなく状態管理の点で苦労しました。ReduxとApollo Clientの状態管理がバッティングするのでその辺りの設計段階で躓きましたね。ReduxではなくApollo Clientメインで状態管理をすると決まったものの、別プロジェクトで行っていた従来のコンポーネント設計の見直しなどが必要になってしまいました。
また、Reduxは更新のフローがルール化されていますが、Apollo Clientでは特にルール化されておらず複数のパターンがあるので、やや無秩序なコードになってしまっている部分があるのも否めません。
──そのあたりはどのように対策されているのでしょうか。
S:現在まさに悩んでいるところです。ReduxとApollo Clientと共存させる方が良かったのかなとも思うのですが、ReduxでやっていたことをApollo Clientで代用する事例がほとんどでしたね。サーバーからのレスポンスはApollo Clientで管理して、それ以外はReduxやカスタムフックで管理しても良いのではないかと考えています。
──試行錯誤されているところなんですね。テストはどのように書かれていますか?
Y:サーバーサイドは全体のアーキテクチャがクリーンアーキテクチャ的な設計になっていて、レイヤーごとにテストするんですね。GraphQLだとクエリによって取るフィールドが決まるので、どこまでのクエリを1個のテストケースで書くべきなのか考える必要がありました。
──全パターン書くわけにはいかないですしね。
Y:はい。基本的にはネストしていないものはそのまま全部取って、したものに関しては次の階層のIDだけを取るといった形で書くことが多いです。
▲「スーパーフレックスタイム制」も導入するなど自由な環境で開発ができるのも魅力
デメリットは少なく、メリットはたくさんある。GraphQLの新たな可能性を探していこう
──GraphQLが向いているもの、向いていないものはありますか?
Y:監視の問題が気になる場合は、RESTの方が良いかもしれませんね。そうでなければ、向いていないものはあまりないと思います。APIの規模が大きかったり、複雑だったりする場合にもおすすめですし、フロントエンド側のUI変更など要件の変更が多い時にも、GraphQLならバックエンド側の修正を減らすことができます。
S:私もYさんと同じで、GraphQLに向いていないものはあまりないのではないかと考えています。導入するデメリットがあまりないと言いますか。何より、APIクライアントとしての機能と状態管理の両方をApollo Clientの柔軟な機能で臨機応変に行うことができるのは大きなメリットだと考えています。
──最後に今後取り組んでいきたいことがあれば、お話しいただけますか。
Y:実際にできるかどうかはわからないのですが、バックエンドをマイクロサービスに分割し、それを集約するレイヤーとしてGraphQL使用するといったより大規模なユースケースに導入すると、いま以上にメリットや面白い課題が見えてくる予感がしています。
──大きな挑戦ですね!Sさんはいかがですか?
S:GraphQLで実装した時とRESTで実装した時で、APIの形式によってUIコンポーネントの設計が変わってしまう傾向がありました。状態管理の機構を大幅に変更したので致し方ないことだとは思ったのですが、APIの種類に関係ないUIコンポーネントの設計の方法を探していきたいなと思います。
──課題を解決することこそが、エンジニアの本質ですものね。本日は貴重なお話をお聞かせいただきありがとうございました!