インターンがGraphQL+Apollo Clientでサービスの管理画面を作った

Kaizen Platformでインターンをしているtokudaです。

Rails、GraphQLを使っているサービスの管理画面をReact, Apollo Clientで作ったことについての記事です。

ReactでAdmin画面を作ることになった経緯

Kaizen Platformのサービスでは、管理画面は基本的にActiveAdmin(データモデルをベースに簡単に管理画面を実装出来るライブラリ)を用いて実装しています。

ActiveAdminは単純なCRUDを提供するアプリケーションを素早く構築することには向いています。

一方で、CS業務フローを効率的にこなせるような管理画面を作るのは難易度が高いです。

管理画面が誰にとっても使いやすい状態になっていると、今働いている人の業務効率も上がるし、新入社員のオンボーディングもスムーズになり、組織としての業務効率を上げられそうです。

この問題に対して、脱ActiveAdminのサンプルとして管理画面のSPA化をすることになりました。

また、開発者にとってはドッグフーディングが活発に行われ、お客さんが直接使わない範囲で改修や技術的なチャレンジを行う場としても期待されます。

ここで検証した新しい技術や便利な技術を将来的にお客さんが使う範囲に適用していくようにしています。

技術スタック

ざっくり、BEとFEの構成は以下のイメージです。

f:id:kaizenplatform:20211126151359p:plain

Rails Engine

バックエンドはRailsで、APIをGraphQL、Admin画面はActiveAdminで実装していました。 それを、今回はActiveAdminから離れ、Admin画面もGraphQLで実装することになりました。

しかし、これまでのサービス用のGraphQL実装にAdminのAPIを追加してしまうと、実装が混在してしまったり、Adminにしか露出させたくない情報が漏れる可能性があるという問題がありました。

そこで、engine化によってAdmin用のGraphqlの実装やSchemaをサービス側と分離することにしました。

エンジン (engine) は、ホストとなるRailsアプリケーションに機能を提供するミニチュア版Railsアプリケーションとみなせます。この場合、ホストとなるRailsアプリケーションは、実際にはエンジンに「ターボをかけた」ようなものにすぎず、Rails::ApplicationクラスはRails::Engineから多くの振る舞いを継承します。

Rails エンジン入門 - Railsガイドより

f:id:kaizenplatform:20211126152517p:plain

また、GraphQLで共通して使用したいtypeなどはこれまで通りapp直下のgraphqlディレクトリ以下に実装することで、コピペを避けています。

engineにすることで、認可の制御漏れやSchemaの肥大化を防ぎ、スッキリした実装になったと思います。

Frontend

フロントエンドはReact + TypeScript + Apollo Clientを基本として、UIライブラリはMaterial UIを採用しています。

詳しいフロントエンドのアーキテクチャについては以前yanoさんが記事を書かれているので、そちらをご覧ください。 developer.kaizenplatform.com

FEではTypeScriptで開発しているので、GraphQLを使う際に型情報が欲しいです。

そこで、GraphQL Code Generatorを使うことで、BEのGraphQL SchemaからCLIを通して、TypeScriptの型情報を生成することができます。

これまでは、BEに合わせて手動で、型を書いていましたが、自動化できたので、効率化になりました。

GraphQL Code Generator

ちなみに、GraphQL Code Generatorは現在ではユーザー用画面のフロントエンド環境でも採用されており、ここでのドックフーディングが活きた形となります。

開発の流れ

この章では簡単に開発の流れについて説明します。

新たにAPIが必要な場合は、 BEでenginesのadmin内で必要なGraphQL APIを実装します。

FEでは以下のようにGrpahQLのクエリを叩くようにしています。

const CAT_FRAGMENT = gql`
  fragment cat on Cat {
    id
        name
  }
`;

const GET_CAT = gql`
  ${CAT_FRAGMENT}
  query GetCat($id: ID!) {
    Cat(id: $id) {
      ...cat
    }
  }
`;

const useCatQuery = (id: string) => {
  const { loading, error, data } = useQuery<GetCatQuery>(GET_CAT, {
    variables: { id: id }
  });

  return { loading, error, data };
};

上のコードのように、GraphQLクエリを書いた状態で、GraphQL Code GeneratorをCLIで実行することで、BE側のSchema情報をもとにCatやGetCatQueryの型が生成されます。

型を生成した後は次のコードのようにコンポーネント内でhooksの返り値のdataで型が使えます。

const { loading, error, data } = useCatQuery({ '123' });
console.log(data.Cat.name)

おわりに

Rails EngineやGraphQL Code Generatorなどこのプロジェクト発で他のプロジェクトでも活用できそうな技術の発見がありました。 組織としての技術的チャレンジの場としてこれからも活躍することを期待しています。

また、個人的にReactをちゃんと使ったプロジェクトが初めてでしたが、BEもFEもやってみたいという希望があったので、それを叶えられて良かったです。

Reactが初めてで、しかもAdmin画面を最初から作るということで、最初は少し不安でしたが、 boilderplateは用意してもらえたし、 フィードバックをもらいながら、他のプロジェクトを参考にしつつ、Reactの勉強をしつつ開発ができました。

お客さんに直接の影響が出ない範囲で、BEもFEも挑戦させてもらえて安心できました。なので、個人のチャレンジの場としても有用だったと思います。

興味があれば、ぜひKaizen Platformのインターンにチャレンジしてみてください! hrmos.co

We're hiring!

Kaizen Platformで一緒に働いてくれる方を絶賛募集中です!

話を聞いてみるだけでもいいので、ご興味ある方はぜひ! hrmos.co