React + GraphQLで社内の負債を解決した話

藤本卓哉氏:みなさん、こんばんは。ジェムクックの藤本です。『React + GraphQLで社内の負債を解決した話』というタイトルでお話ししたいと思います。よろしくお願いします。

まず簡単にプロフィールです。藤本卓哉と言います。去年(2019年)30歳になって、今年(2020年)31になります。会社の代表兼エンジニアをやっています。会社の代表といったら、経営ガッツリやっているんかなって言われがちなんですけど、僕けっこうエンジニアメインです。React、React Native、TypeScript、Go、AWSなど、CTOとまでは言わないですけど、技術にはガッツリ絡んでいます。

ヤフーと一緒にやっている会社ジェムクックとは?

まず会社紹介です。株式会社ジェムクックという会社です。本社は大阪にありまして、スカイビルから徒歩5分くらいのところです。会社を建てたのが2016年。もう今から4年前ですね。

社員数とかはそんなに多くなくて、アルバイト込みの16人くらいです。会社のバリューとしては、好きな人を喜ばせるためにプロダクトを作ることを自分たちのマインドとしてやっています。左下にあるのが会社です。

主にエンジニアとかデザイナーが集まってアプリを作っている会社です。スタートアップみたいに、自社アプリだけをメインで作っているわけではなく、クライアントワークもやっています。

最近は社内のリソースがちょっと余ってきたっていうのもあって、やっと、本来やりたかった自社サービスの開発にも着手できているというようなイメージです。

インプットとアウトプットを大事にする

僕たち16人くらい社員がいる中で、13人くらいはエンジニアなので、エンジニア論というのをすごく大切にしています。僕たちはエンジニアなので情報のインプットとアウトプットを徹底していますというのが、僕らがいつも言っていることです。

どういうことかと言うと、まずは旧態依然とせずに、積極的にモダンな技術を採用しています。まあ、流行っているだけでガンガン採用するというわけではないんですけど、新しく出た技術はどんどん積極的に採用して社内のリソースをまかなっています。

アウトプットのところでは、OSSの開発ですね。これ最近はちょっとメンテ止まっているんですけど、Reactのライブラリを14個くらい出している時期がありました。めっちゃ古いですね。いいときで2700くらいダウンロードされたりとか。React黎明期のときにはけっこうよかった。会社にまあまあフロントエンドのエンジニアも増えてきたのでまたメンテしようかなという感じです。

(アウトプットと言えば)今日のMixLeapもそうです。今日がなんとヤフーさんと5回目のMixLeapということですごく嬉しく思っています。初めてのオンラインでというところにも選んでもらって、中川さんありがとうございます。今後もしっかりアウトプットの一環としてMixLeapでのつながり、情報提供というのはしっかり意識してやっていきたいと思っています。

あとエンジニア募集しています。ReactとかGo。ほとんど社内の開発はReact、Goでやっているので、もし興味ある方いたらWANTEDLYでもいいですし、僕にTwitterとかダイレクトメールでもいいですし、ぜんぜん応募してください。お待ちしています。

GraphQLを採用するまでの経緯

ちょっと長くなっちゃったんですけど、GraphQLを採用するまでの経緯。本題に入っていきたいと思います。

なんでGraphQLを入れたいかって話ですが、最近自社サービスの開発がグッと始まったんですね。コロナの影響でリリースは止めているんですけど、映画で出会えるMiyouというマッチングサービスを出そうと社内で決めて、開発に勤しんでいました。

なんですけど、「チャットがいるよね」となって。いつもチャットっていうと、だいたいFirebaseを使ったりとか、そのあたりで調整していたんですけど、社内のスタックがAWSで全部できているというのもあって、AWSでなんとかしたいという思いがありました。

AWSにはAppSyncというGraphQLベースのサービスがあります。そこでチャットがいるならGraphQLを使おうっていうので採用しました。

GraphQLはサーバに問い合わせる新しいクエリ言語

GraphQLについてどういうものかを簡単に説明すると、Facebookが開発しているWeb APIの規格です。言語というよりは規格というイメージです。

じゃあ規格って何だ? って言ったら、A query language for your APIっていうのがGraphQLを表すものなんですけど。APIのためのクエリ言語ですね。もうちょっと平たく言うと、APIで使用するための問い合わせ言語と言われています。

じゃあ次、クエリ言語って何なんだ? ってなるんですけど。よくみなさんがイメージするのはSQLですね。SQLもクエリ言語って言われているものですが、データベースに対して問い合わせを行うクエリ言語です。

それに対してGraphQLは、あるサーバに対してデータを問い合わせできる別の形式の新たなクエリ言語。対象のリソースが違う感じですかね。データベースにいくのかサーバにいくのか。GraphQLはサーバにいく新たなクエリ言語です。

GraphQLの3つの特徴

GraphQLの3つの特徴。これは公式サイトを引用しています。

Ask for what you need, get exactly that A query language for your API. これは何かと言うとサーバに対して必要な分だけ過不足なくデータを取得できる。あとで社内の負債を解決した点でも説明しますが、要はAPI。フロントのUIが変わりましたってなるたびに、いるデータ、いらないデータというのがすごく変わってくると思います。フロント側が指示をして必要な分だけデータをもってくることができるというのが1つ目の特徴です。

2つ目の特徴。Get many resources in a single request.。一度のリクエストで関連するデータをまとめて取得できる。これもGraphQLのすごくいい点です。どういうことかと言うと、例えばREST APIだったら100本くらいのAPIを作って、その中で2、3本まとめてAPIを投げて、それを組み合わせてどうたらこうたらするっていうのがよくあるあるのパターンだと思うんですけど。そうではなくて1回のリクエストでそのページ、そのUIで必要なデータをまとめて取得できるっていうのがGraphQLのいいところですね。

3つ目、Describe what's possible with a type system.。これは型システムと言われています。何かと言うと、GraphQLでは必要なデータは必ずフィールドを指定して要求します。型ですよね。nameだったらStringとか、friendsだったら配列だとか、そういったかたちでフィールドが決まっています。フィールドは必ず型が決まっているので、サーバサイドから返される型は常に定まっているというふうになります。

これで何がいいかと言うと、フロントエンドがバックエンドに求めたとき、確実に思っている型で返ってくる、安心性が増すと言ったほうがいいですかね。安心性が増すので、GraphQLを使うことによって保守性なり安心性が高まると言われています。

実際の例がこんな感じです。左の図のREST APIというところです。クライアントはさまざまいます。その中でいろんなエンドポイント、ここだったら/postsと/usersっていう2例ですね。これをいろんなかたちで叩いて、いろんなリソースにアクセスいくきます。

ここがGraphQLだったら、/graphqlっていう1つのエンドポイントに対してデータベース1つ、まあここは複数でもいいんですけど、何個も何個もエンドポイントを用意しなくても、1回リクエストしたらほしいものだけ返ってくるかたちになります。

右の例にはクエリの書き方の例を一応載せました。右の図の左側のqueryとかですね。usersのid、name、bioがほしいってなったらそれをqueryに書くと、その分だけのデータが返ってくるかたちです。これだけ見てもすごくシンプルですね。

AppSyncでGraphQLの導入コストを下げる

とは言っても導入コストかかるんでしょ? ここは僕も実際思ったところで、これを簡略化するためにAWSのAppSyncサービスを導入しました。サーバーレスのかたちでGraphQLのバックエンドを実装できるフルマネージドなサービスです。

GraphQLってけっこう初期導入するときが大変なんですよね。例えばフロントエンドはこう、バックエンドはこうって……。結局はさっきのこの画像でも出てきた/graphqlっていうピンクの丸のところ、ここは自分自身で実装しないとダメです。

AppSyncを導入するとどうなるかと言うと、自分自身の実装をAWSにまるっと任せちゃえる。GraphQLの導入障壁がかなり低くなります。

かつ、GraphQLで気になる細かい仕様、ここはまあいろいろとあるんですけど、やっぱり一長一短で、例えばキャッシュが効きにくいとか、エンドポイントが1つになるのでキャッシング難しいよねとか、GraphQLってよく言われるんですけど、そのへんがうまいことAppSyncだったら解消できるようになります。

GraphQLでこう変わった

GraphQLを実際に導入してみてよかった点。僕はAppSync上でGraphQLをやろうと思ったので、AppSyncは導入している前提です。これまでの社内の負債というのがこんな感じでありました。

APIを100本とか作るとエンドポイントがいっぱいできちゃうよとか。これはみんなあるあるだと思うんですよね。大きいプロジェクトになればなるほど、「posts/なになに」「todo/なになに」とか「users/なになに」とか、APIがかなりの数になって、フロントエンドでもどれを叩いたらいいんだとか悩むシーンが増えると思います。

それからこれを叩いたらこういうレスポンスがあるんだというAPIドキュメントですね。これもやっぱり管理するべきもので、メンテが追いつかないとか、フロントエンドは叩いているけど、実は違う型が返ってきたとか。ドキュメントが常に整備されているかと言ったらそうではない状況だったので、そこの管理コストもかかっていました。

弊社だけかもしれないですけど、どちらかと言うとAPIドキュメントを管理しているのはバックエンド側だったので、バックエンドの人もフロントエンドから「ちょっとAPIドキュメント最新じゃないんですけど」というかたちで、「あ、じゃあメンテします」というように、バックエンドの方はすごく大変そうでした。僕はどちらかと言うとフロントなので、あんまりだったんですけど(笑)。

そして画面で必要のないレスポンスも大量に返ってきていた。APIが明らかに多い。最初の設計では必要だったかもしれないけど、のちのちはいらなくなったデータとかも全部返ってきていた。ここもわざわざUIが変わるたびに毎回毎回API側をいじるっていうのもナンセンスで、そのままにしていたという感じでした。

あとこれはダメなことではないんですけど、チャットを実装するときはFirebaseを使っていた。チャット以外は基本全部AWSでまかなっていたので、Firebaseからは脱却したいなぁと……。バツってわけじゃないんですけど、脱却したいなと思っていました。

その理由としてはコンソールが見慣れないし、認証周りは全部Cognitoでやっているんですけど、そのへんとの兼ね合いも考えて、やっぱりAWSのリソースでなんとかしたいなと思っているのが社内の負債として残っていました。

GraphQLを導入してどうなったかと言うと、まずはGraphQLの機能と言っていいんですかね。Subscribeという機能があって、それでチャットが簡単に作れました。エンドポイントが1つになって、100本このエンドポイントを叩かないととか、あのエンドポイントを叩かないととかいうエンドポイント地獄から解放されました。

そしてフロントがほしいデータだけ取得できるようになった。これはすごく良くて……。フロントでもしっかり型の意識というのができますし、バックエンドとのコミュニケーションもすごく取りやすくなりました。

それからさっきちょっと言ったAPIドキュメントですね。APIドキュメントがバックエンドの仕事だと言いましたが、フロントエンドでもGraphQLのサーバのSchemaを定義することで型をどっちが担保しないとダメなんだとか、APIドキュメントのメンテは誰がやらないとダメなんだっていうのがなくなりました。フロントエンドの責務としてSchemaを管理するというふうにしたら、バックエンドの負荷もかなり減ったというような感じです。

あとはFirebaseをやめたのでAWS内で完結したっていうのがGraphQLを入れてよかった点ですかね。

チャットもできたし、今までの負債が見事に解決できる。GraphQLを入れることで社内のリソースというか、フロントエンドの頭もスッとするし、バックエンドの負荷も減ったので、僕的にはGraphQLを入れて、すごくよかったなと思っています。

GraphQLのつらいところ

逆にGraphQLを入れてつらかった点というのもあります。これはけっこうAppSyncの話も入ってきているので、AppSync使わなかったらというところもあります。AppSyncには、例えばさっきのGraphQLのサーバを立てて、そこからどのリソースのどのデータを取得したいかっていうのを書く必要があります。それはリゾルバーマッピングテンプレートというものなんですが、ここの管理方法については調査して対応する必要がありました。

うちはサーバレスフレームワークでGraphQL、AppSyncを使っているんですけど、GraphQL、AppSync用のいい感じのプラグインがあったので、それをバージョン管理しているっていうような落としどころです。

あとはリゾルバーを書くためにVTLというJavaベースの言語みたいなのを使うんですけど、これが初めてなので見慣れない。AWSの中の人とちょっとしゃべる機会があって、その方にも言ったんですけど。「ごめんなさい」くらいの感じでした(笑)。

次に、コードの書く量はどうしても増えますね。上のリゾルバーマッピングテンプレートっていう中間サーバの役割をするところの記述は、どうしても記述量は増えてしまいました。

ただ記述量が増えたからといってバツだっていうわけではなくて、コード量はたしかに増えるけれど、頭がすっきり、後から入ってきた人がわかりやすいという状態は作れているので、コード量が増えるというのは、僕はあんまりマイナスとは思っていません。

次がすごく大事なところです。チームへの布教、教育というのは、めちゃめちゃ必要でした。これは何かと言うと、やっぱりGraphQLというのは見慣れない。モダンな開発をしている会社であれば、ぜんぜんGraphQL当たり前だよねとか、GraphQLに興味があって早めに導入している会社とかもあると思うんですけど……。

どうしてもREST主体な今の世の中だと思うので、なかなかGraphQLへの理解というのは大変でした。僕は自分で会社やっていて自分で技術を決めることが多いので、トップダウンで落とし込んだんですけど、それでもやっぱり教育の部分は大変で……。ここは今までと違ってこうしていこう、ああしていこうっていう教育はかなり大変でした。

あとここは、これもちょっと難しい。自分で書いていて「う~ん」と思う部分もあるんですけど、RESTで取得したくなる気持ちと戦う必要があった。これは何かと言うと、RESTで叩きたくなるんですよね(笑)。どうしても。

GraphQLを通さずにRESTで叩きたいなというところ、ここはRESTで叩いたらいいと、今は思っています。一時期躍起になってGraphQL全部通すんだ、エンドポイントの数をちょっとでも減らすんだって躍起になっているときがあったんですけど、ここはケースバイで、API直で叩くというのは、ぜんぜんそれはそれでよくて……。しっかりとメンテさえできていたらいいかなと思っています。

GraphQLを採用したらフロントエンドとバックエンドが仲よくなれた

まとめます。GraphQLを採用したらフロントエンドとバックエンドが仲よくなれた。これ実際になれました。一番多かったAPIドキュメントがメンテできていない問題は解消できて、フロントエンドがしっかり型を書くという文化ができたのですごくよかったです。

どこの会社でもありそうな技術的負債が解消できた。これもすごくよくて、APIが、100本がどうやこうやとか、いろいろ負債はあったんですけど、GraphQLという1つの技術を入れることでいろいろな負債が解消できたので、そこも満足しています。

最後、チームへの布教と理解、教育っていうのは絶対必要。ここが一番大事だと思っています。ぶつかり稽古じゃないですけど、こういう感じでここはどうなんだ、ああなんだっていうディスカッションも必要ですし。チームに理解してもらう。

こういうふうに使うんだよっていうふうに教育していかないと、むしろGraphQLを導入したことによって開発がうまく進まないとか、みんなやる気なくす……まあそれはないとしても(笑)。結局はプロダクトが前に進むことが大事だと思うので、そこが叶わない可能性はあるなと思いました。

最後に、しっかり布教と教育ができればこれ以上ない技術。フロントエンドにとってもいいものなんじゃないかなと思っています。以上です。ありがとうございました。