COMPASSの技術スタック紹介
はじめに
こんにちは!株式会社COMPASSの技術責任者の仲谷です。
私はシステム開発部というエンジニアリングの組織で、技術選定やアーキテクチャの設計などの技術に関するマネジメントを日々行っています。
COMPASSで採用している技術の中には、長く採用し続けているものもありますが、技術の進化に伴って新たな技術を選定していくことも重要だと考えており、日々最適なシステムとは何かを追い求めながら開発を行っています。
そこで、今回はCOMPASSで現在利用している技術スタックを背景と共に紹介します。
この記事はこんな方におすすめ
- 株式会社COMPASSの技術スタックを知りたい方
- 技術選定の観点などを知りたい方
技術スタックの紹介
COMPASSでは、AIが子どもたち一人ひとりに合った問題を出題する公教育向けのデジタル教材「Qubena(キュビナ)」を開発、提供しています。現在では100万人を超える子どもたちが公立の小中学校でキュビナを利用して学習を行っています。
また、子どもたちの学習状況を先生方が確認・サポートするための先生向けのツールとして、「キュビナマネージャー」という管理ツールも提供しています。
このように、公教育の現場では子どもたちだけではなく先生方も利用するサービスとなっていますので、それぞれのユーザーに最良の体験を提供するために様々な技術を検討し、採用しています。本記事では、その技術スタックについて詳しくご紹介します。
フロントエンド
TypeScript + React + Next.js
フロントエンドは、子どもたち、先生方が直接触れる部分のため、最良の体験を届けるにあたって非常に重要な部分であると考えています。
キュビナのサービス立ち上げ当初など、複雑なフレームワークなどを使わずに開発を行っていた時期や、プロダクトごとに異なる技術を採用していた時期もありましたが、急速に進化する技術トレンドに迅速に対応できるように、技術選定をプロダクト全体で統一しナレッジの共有をしやすくしてきました。
上記のように、異なる技術を使っていた所からプロダクト全体で技術を統一するのにはやはり労力と時間がかかりましたが、最終的な費用対効果を考えると、良い意思決定ができたと考えています。ということで、現在ではTypeScript + React + Next.jsでフロントエンドの技術を統一しています。
選定理由としてはそこまで複雑ではありませんが、型安全で記述ができることからTypeScriptを、子どもたち、先生方が利用する際にストレスがないよう、レンダリングの最適化を行いたいという背景からReact + Next.jsを採用しています。
次に、ライブラリの紹介です。
コンポーネントライブラリにはGoogleのMaterial Designをベースに開発されたMUIを用いています。コンポーネントの豊富さや、デザインの一貫性の担保、拡張性、メンテナンス性の良さなどを考慮してMUIを採用することとしました。データ通信にはTanStack Queryを利用しています。
TanStack Queryについては前バージョンのReact Queryの時代から採用しており、比較的当初新しかったフレームワークではありましたが、COMPASSでは使い勝手の良さに非常に期待しており、採用当初からGitHubにてスポンサーとして支援しています。
良いOSSにはスポンサーとして積極的に支援を行っています。
出典: https://react-query.tanstack.com/
以下の記事に詳細がありますので参考までに。
https://note.com/santadesu/n/n7c6cd8029c4d
また、状態管理は最近MobxからJotaiに移行を行っています。
状態管理については色々アプローチがある中、Jotaiも比較的新しいライブラリとなっているのですが、記述量が少なくすっきりとした実装になるところが魅力で、新しいながらも技術的なチャレンジも含めて採用に踏み切った技術になります。
また、フロントエンドの開発に際し、エンジニアだけではなくデザイナーと議論を行いながら最適なUIを作っていくことが重要だと考えています。
そこで、コンポーネント単位で実装確認とビジュアルテストを効率よく回せるように、Chromaticを採用しています。Chromaticを採用することで、コードベースではなくUIベースでレビューができるようになりました。
現在のバージョンのキュビナのリリースは2021年になりますが、ローンチしてからも常に最新の技術動向をキャッチアップし、より良いプロダクトになるよう日々進化を続けています。
バックエンド
Scala
キュビナのコアプロダクトではScalaを採用しています。
冒頭に記載した通り、キュビナ はAIが子どもたち一人ひとりに合った問題を出題するプロダクトとなっています。
その中で、子供たちが学習の過程でどのような問題をどのように解いたか、どのように間違えたか、どれくらいの時間考えたかなどの膨大なパラメータを記録しています。
そしてその膨大なパラメータを元に次に解くべき問題をAI で推測して出題を行う必要があります。単純なWebシステムであればそこまで計算量を気にする必要はないのですが、上記のように膨大なパラメータを元に複雑な計算を行うため、やはり一定以上のパフォーマンスが出せることが必須要件となりました。
また、選定当時は計算に用いる膨大で複雑なパラメータを表現するために後述するJanus Graphの採用が決まっており、ライブラリがJavaで提供されていることからJavaかScalaが選定の候補となりました。
最終的にはScalaが持つ強力な型システム、関数型の記述による幅広い表現、マルチパラダイム言語でオブジェクト指向型でも記述可能な点を踏まえて当時Scalaをかけるエンジニアは社内にいなかったのですが、思い切ってScalaを採用することにしました。
現在のキュビナの一つ前のバージョンのキュビナではバックエンドにpythonを採用しており、まさにパフォーマンス面、メンテナンス面での課題に直面していたのですが、Scalaを採用したことによって同じ処理も記述量が少なく、かつ高速で動作させることができるようになりました。
ライブラリとしては、選定当初はAkkaを用いたCluster Shardingなどを行うことで負荷軽減を試みていましたが、非常に強力な技術である反面、システムの複雑化を招いてしまうというデメリットもあり、現在では利用していません。(この辺りはまた別途記事にさせていただければと思います。)
現在利用しているライブラリとしては、Pekko、Slick、Airframe等がありますが、こちらも今後極力シンプルな構成にしていくにあたり、場面に応じて選定する技術を改善していきたいと考えています。
また、サービス間通信ではこちらもパフォーマンスを重視してgRPCを採用しました。gRPCに関しては、Protocol Buffersを用いたインターフェース定義に採用メリットを強く感じているため、今後も継続して採用していく予定です。
Database
RDSとしてはMySQL、キャッシュとしてRedis、グラフデータベースとしてJanusGraphを採用しています。
MySQL、Redisに関しては一般的にもよく使われていると思いますが、グラフデータベースであるJanusGraphの採用は他社と比較しても珍しい例だと考えています。
JanusGraphに関する現在の見解については後述しますが、選定の際の要件として、膨大で複雑なデータを表現できる必要がありました。
具体的には、子どもたちが習得する知識要素を定義、表現しようとした際に、当初の構想ではグラフ構造で表現することが理想的であり、グラフ構造をそのまま格納できるデータベースとして選定したのがJanusGraphでした。
当時はNetflixのバックエンドがグラフデータベースとRDSを組み合わせていたことなども考慮し、最新のアーキテクチャを目指した結果、このような形になりました。一方で、選定当初と現在ではシステムで考慮すべきポイントがやや変わり始めているので、今後はこの部分に対しての改善を行っていく想定です。
インフラ
クラウドサービス
クラウドサービスはGoogle Cloud Platformを利用しています。
こちらも前バージョンのキュビナではAWSを利用していましたが、100万人を超える子どもたちが利用するインフラとなると計算コスト、ネットワークコストが非常に大きなものになり、選定当初設計した構成に対してコストメリットが大きかったというのが選定の大きな要因になります。
一方で、Google Cloud Platform特有の機能に強く依存しているわけではないので、今後も構成やアーキテクチャの変更に伴って柔軟に動いていこうと考えています。
また、コンテナオーケストレーションツールとしてはKubernetesを、IaCツールとしてはTerraformを採用しており、クラウドネイティブな開発環境を実現しています。
CI
開発プロセスの効率化と品質向上のために、継続的インテグレーションツールを活用しています。
主に採用しているのはCircleCIとGitHub Actionsです。CircleCIは、ビルドとテストを自動化するのに用いており、GitHub Actionsはデプロイ周りのワークフローを一部自動化して運用しています。
今後より開発プロセスの効率化を行っていくためにも、CI周りの改善については力を入れていきたいと考えています。
監視
監視ツールとしてはSentry、Datadogなどを用いています。
監視といってもSentryなどのアプリケーションのエラーを監視するものから、インフラの状態を監視するものなど様々な角度がありますが、キュビナの運用に関して最も注意すべきなのは、子どもたちが集中して使う際のパフォーマンス監視です。
キュビナはサービス特性上利用される時間のピークに傾向があり、その中でも朝の8時から9時くらいまでの時間帯は学校が一斉に始まるので、最も多くの子どもたちが利用する時間帯となります。
新機能や改善のリリースを行った際に、ピークタイムのトラフィックを捌けるかという観点から、パフォーマンス監視についてはかなり手厚く行っており、ダッシュボード化して常に監視ができるようにしています。
技術選定からの振り返り
初期の技術選定から時間が経過し、特にScalaの技術者確保の難しさや、JanusGraphのユースケースとのギャップにおける性能問題が課題として浮かび上がってきました。
これらの課題に対する対応策や、新たに見出した解決策については、別のブログ記事で深堀りしていく予定です。
私たちは技術選定を、単なる一時的な決定ではなく、絶えず評価し続けるべきプロセスと捉えています。技術スタックを進化させ、適応させていくことがプロダクトをより良くするために必要不可欠であると捉えています。
まとめ
COMPASSの技術スタックは、公教育を支えるサービスとして、堅牢でスケーラブルである必要があります。
フロントエンドからバックエンド、インフラまで、一貫した技術選定により開発チームのナレッジ共有を促進し、効率的な開発フローを実現しています。
今後も技術の進化とともに、スタックの更新を進め、プロダクトの品質向上を目指していきたいと考えています。
Discussion