見出し画像

KEPPLE DB リニューアルで GraphQL を採用しました

こんにちは! KEPPLE CREATORS LAB の Product Development Section でエンジニアをやっている芹田です。

今般、弊社のサービスである KEPPLE DB のリニューアルを行いました。
ぱっと見では、UI の刷新とレスポンスの改善を行なっただけですが、実は裏側には別の目的がありました。それは、一気に技術的負債を返済し、開発リードタイムを縮め、より早く価値提供することです。
今回は、その中でも特に開発効率を上げる観点から GraphQL を採用した背景と経緯をお話しします。


なぜ GraphQL なのか

リニューアル後の KEPPLE DB は、フロントに Next.js、BFF に NestJS を採用し、既存のデータソースと KEPPLE CRM のサーバーに対して BFF が REST API でアクセスする構成になっています。そして、フロントと BFF の間の通信に GraphQL を採用しました。
主な理由は以下の通りです。

  • 同じデータソースからデータを取得するけれども、使用するプロパティが異なるシチュエーションがかなり多かった (オーバーフェッチを防ぐ手間を減らしたかった)

  • 「そのページで必要な情報が何なのか」を知っているのはページなので、ページに定義するべき (クエリを書くべき) だと考えた

  • フロントエンドで型安全にデータを扱いたかった

KEPPLE DB はスタートアップと投資家のデータベースで、各データのプロパティがとても多いため、オーバーフェッチを防ぐための処理を手で書かないでよいのは大きなメリットです。
また、必要なプロパティをページに定義することで、フロントの作業とBFFの作業の依存性が低くなり、コンテキストスイッチのコストを減らせます。

型安全性については、TypeScript に閉じた世界であれば REST API を採用した場合も aspida などの優秀なライブラリを使用することで型安全にデータを扱うことができます。ただ、複数言語・複数プロダクトが関わる状況では、OpenAPI における required と null の解釈がライブラリによってまちまちで、過去に別プロダクトで「プロパティが存在しないことを期待したら null が返ってきた」「プロパティが存在することを確認してからアクセスしていたが null 参照でインシデント発生」などの経験があり、別のエコシステムにベットしてみたいという想いがありました。

初めての GraphQL 

ケップルではプロダクトに GraphQL を採用した実績がなく、今回が初めての採用だったので社内勉強会を開催しました。

もともとラボには気軽に勉強会を開く習慣があったことから (もしよければ『社内勉強会を1年間続けてわかった、勉強会を活発にする5つのポイント』をご覧ください!) 勉強会の知見があり、GraphQL においては以下の方針でやっていました。

  • Production Ready GraphQL を教材に採用して週に 1 回の輪読会を行う

  • 持ち回りで準備するが、基本的に準備は頑張らない

    • しっかり準備するより、その場で全員で読んで議論したほうが効率的だと考えた

    • 実際、DeepL や ChatGPT で翻訳してさらっと眺めてから会に臨むことが多かった

  • 人間の集中力はそんなに長く保たないので 40 分で終わらせる

    • セクションごとに、内容の解釈や、KEPPLE DB に適用するならどうするのがよいかを議論していたが、白熱することが多く、読むのがなかなか進まない

  • 最後に次回どこを読むか決める

この勉強会のおかげで、実際に実装するときには GraphQL の基礎的な知識があったため、基本的なところに悩むことなく実装に集中することができました。少し特殊なケースも「Production Ready GraphQL のあのページに書いてあったやつを応用すればいけるよね」のような感じで解決できたので、かなり役に立ったと思います。

Production Ready GraphQL はとてもよい本なので、GraphQL を採用する際にはぜひ読んでみてください。行間が多い本なので、ひとりで読むよりチームで読むのがおすすめです。

技術選定

具体的な技術選定について紹介します。

BFF

NestJS + Apollo Server + Express の組み合わせです。

NestJS

今回、フロントと BFF を両方とも TypeScript で開発しようという方針でした。ケップルでは NestJS の使用実績があり、あえて他のフレームワークを使用する動機がなかったので、BFF には NestJS を採用しました。

Apollo Server + Express

NestJS で GraphQL を使用する場合、NestJS のバックで Apollo Server/Express を動かすか Mercurius/Fastify を動かすか選ぶことができますが、運用上の都合で社内で既に実績がある Express を使用するため、Apollo Server/Express を採用しました。

ドメインごとにモジュールを分け、Resolver とドメインの Service とデータフェッチの Service の3層に分けるだけのシンプルな構成です。そこにロギングやエラー処理のためのミドルウェアを追加しています。

NestJS で REST API サーバーを実装するのに比べると、NestJS で GraphQL サーバーを実装するのは情報が少ないです。ただ、NestJS 公式の Discord を参照したり、Apollo Server のドキュメントを読んだり、NestJS のソースを読めばなんとかなるため、そこまで苦労しませんでした。

Code First

NestJS ではコードファーストとスキーマファーストの両方のアプローチを選択できます。今回はコードファーストを選択しました。
KEPPLE DB に関わるエンジニアは全員フロントとバック両方を担当すること、どちらも TypeScript で記述することから、コードファーストのほうが開発効率がよいと判断しました。

フロント

Next.js + urql + GraphQL Code Generator の組み合わせです。

Next.js

ケップルではほぼすべての Web アプリケーションで React を使っています。React で SSR するので、手堅く Next.js を選択しました。

urql

フロントの GraphQL クライアントには urql を採用しました。シンプルで分かりやすいことを重視しました。
ドキュメント通り設定して `useQuery` や `useMutation` を呼び出すだけです。
いくつかラッパーを用意したり、エラー処理のためのミドルウェアを書いたりはしましたが、特筆すべきことはありません。非常に便利です。

GraphQL Code Generator

デファクトスタンダードで、特に採用しない理由はないと思います。ほとんど client preset のデフォルトのままで使えて便利です。
なお、以下の設定が型安全性の面で便利でした。

  • `defaultScalarType` を `unknown` にする

  • カスタムスカラーを string の Branded Types にする (Nominal Typing)

簡易的な構成図

実際に実装して悩ましかったポイント

しっかり準備してから実装に入ったこともあり、REST API との文化の違いに苦しむこともあまりなく、スムーズに進みましたが、悩ましかったポイントを3つご紹介します。

クエリをどこに書くか

今回は Next.js の Pages Router を使用しているため、getServerSideProps とコンポーネントの両方で同じクエリを呼び出す必要があります。そのため、ページ単位でクエリを定義することにしました。
App Router 移行後は、ページ単位でクエリを定義するのではなく、コンポーネント単位でクエリを定義するように変更できるかもしれません。

Int が 32bit

よく知られた GraphQL の制限です。案外あっさり桁溢れします。KEPPLE DB では資金調達額など金額の大きい数値を扱うので、カスタムスカラーを定義してそちらを使っています。

REST API が向いている処理は素直に REST API にする

ファイルダウンロードや認証など、REST API のほうが向いているものは素直に REST API にしました。無理に GraphQL に統一しないほうがよいと思います。
GraphQL でアクセスするときは必ずトークンがある前提のほうが承認のロジックがシンプルになります。

まとめ

今回は KEPPLE DB のリニューアルの中で GraphQL の話題をピックアップしてお届けしました。GraphQL に決めたときは不安でしたが、実際に実装してみると、とてもよい選択だったと思います。
ただ GraphQL はすべてにおいて REST API より優れているわけではないので、そのときそのときで真摯に技術と向き合って選定していくことが大事かなと思います。


WE ARE HIRING!

KEPPLE CREATORS LAB では一緒に働くメンバーを募集しています。
募集しているポジションの詳細はこちらをご覧ください。

▼KEPPLE CREATORS LAB ブランディングサイト

▼KEPPLE CREATORS LAB 求人一覧


この記事が参加している募集

仕事について話そう

この記事が気に入ったらサポートをしてみませんか?