キカガク プラットフォームブログ

株式会社キカガクのプラットフォームブログです。エンジニアやデザイナー、プロダクトマネージャーなどが記事を書いています。

キカガクの技術スタックと選定理由

はじめに

こんにちは、キカガク CTO の祖父江です。本記事ではキカガクの技術スタックとその選定理由を書いていこうと思います。これまで他社の記事を拝見し、大変参考にさせてもらっているので私たちも次の方へ貢献しようという想いで執筆しています。

これから技術選定フェーズの方が少しでも参考になれば嬉しいですし、キカガクに興味を持っていただけるキッカケになっていただけると幸いです。

TL;DR

技術スタック

結論、キカガクでは以下の技術選定をしています。

  • フロントエンド:TypeScript, Next.js, Chakra UI, Firebase JavaScript SDK
  • バックエンド:TypeScript, Node.js (Cloud Functions), Python (FastAPI)
  • インフラ: Firebase, GCP (GAE, Cloud Run, Cloud Functions, Cloud Storage, BigQuery, etc...)
  • データベース:Firestore
  • 認証:Firebase Authentication
  • 開発ツール:GitHub, Notion, Figma

システム概要図

システム概要図

全体構成を簡易的に表現すると上記のようになっています。メンバーが持っている開発スキルとチームのレベルに合わせた構成を採用しています。エンジニアチームがまだまだ小さいため、運用負担の最小化のためにサーバーレスアーキテクチャを積極的に取り入れています。

フロントエンド

TypeScript

いまではどのチームも当たり前のように採用されていますが、チーム結成当初は JavaScript を選択していました。しかし開発を進めていく中で、チーム開発をするには暗黙のルールが存在してしまい生産性が落ちることが問題になることから、早々に静的型付け言語である TypeScript を採用しました。

TypeScript × ESLint × Prettier の設定を入れておくと最低限のコード品質が担保されるのですが、開発途中から入れようとするとめちゃくちゃ怒られて修正が大変になりますので、プロジェクト発足当初から入れておきましょう。

チームが 10 人近くなってもコード理解がスムーズですので良い選択だったと思います。もう型付けがない言語を触れない体になってしまいました。

Next.js

Next.js

kikagaku.ai はリリース当時 Nuxt.js(Vue2) を採用していたのですが、今年 4 月末に 4 ヶ月に及ぶリプレイスを完了させ、Next.js になりました。もともと Nuxt.js を採用した背景としては当時 JavaScript に強いメンバーが居なく、Python などのバックエンドに慣れているメンバー構成だったため、HTML, CSS, JavaScript の 3 つがきれいに分離されている Nuxt.js 形式が手に馴染みやすかったためです。

しかし、初期の開発体制が整えきれていなかったため、コードがスパゲッティコードになっていたり、コーディングルールが曖昧だったことで後から参画していただいたメンバーがコードを認知するコストの増加が高くなってしまいました。

開発開始から 1 年半が経ったタイミングで大きくリファクタリングを実施するか別言語へリプレイスをするかの 2 択に迫られました。これはエンジニアの開発生産性の視点と経営戦略として kikagaku.ai をより大規模なプロダクトにする構想が立ち上がったのも大きな理由です。

結果として Next.js を採用しました。採用した理由は以下の 2 点です。

  • エコシステムと開発コミュニティの成熟度の高さ
    • プロジェクト継続の安心感がある
    • 開発コミュニティが大きい
    • React 系ライブラリが豊富
    • Zero Config で DX(Developer eXperience)が高い
  • ページ単位で CSR, SSR, ISR などの機構を選択可能

最近は Vercel にロックインしているという声もあがっていますがプロジェクト継続の安心感はありますし、ライブラリが豊富であったり、Zero Config である程度最適化された状態で DX が高いのも満足しています。

Chakra UI

Chakra UI

Tailwind CSS と迷いましたが UI ライブラリである Chakra UI を採用しました。選定理由は大きく以下の 3 点です。

  • 素の CSS を書く必要がない
  • デフォルトで提供されているモーダル、スケルトン、ボタンなどの UI が整っている
  • デザインルールが定義されているため、深く考えなくても UI が整う

これまでは Sass ベースで CSS を書いていましたが、CSS に特別強いメンバーが居たわけではなかったり、業務委託のデザイナーさんとどこまで Component 単位で Code Splitting するかなどのルール整備が困難でした。また、これからさまざまなメンバーが参画していくことを考えたときに誰が書いてもそれなりに UI が整うことは開発速度向上、ユーザーのアクセシビリティの観点からも必要な要素でした。Next.js との相性も良く Props で直感的に記述することができるため、開発速度は実際にかなり向上されました。

少し文脈がずれますが、今後は Chakra UI から提供されている Figma を活用したデザインシステムを構築予定です。デザインシステムによりデザイナーとエンジニアの認識合わせがしやすくなりますし、デザインの一貫性が一定担保されることによって、簡易なパーツであればデザイナーを介さずにエンジニア自身が作成することができれば、さらなる開発速度向上に寄与することを期待しています。

Jest × Firebase Local Emulator Suite

ユニットテスト環境は Jest と Firebase Local Emulator Suite を活用しています。Jest は言わずもがなですが Firebase が提供する Emulator も優れものですので、後日記事で執筆予定です。

バックエンド

バックエンドは Cloud Functions (Node.js) と Python (FastAPI) を採用しています。e ラーニング上でのテスト回答システム (Cloud Run) の裏側であったり、Cloud Functions を採用する部分と採用しない部分の切り分け、デプロイ管理方法などを後日記事化していきます。

Firebase

キカガクでは Backend as a Service (BaaS) である Firebase を採用し、データベースを Firestore、認証を Firebase Authentication を使用しています。まず Firebase には賛否がありますが、特に小規模チームで最速でアプリを立ち上げたいユースケースにおいて素晴らしい選択だと思います。ウェブとモバイルの開発が迅速にでき、リアルタイム性があり、スケーラビリティも高い水準にあります。また、Cloud Functions や BigQuery などの GCP サービスとの連携が容易なところも嬉しいポイントです。

とはいえ、弊社も初期は NoSQL のお作法に悩まされ、スキーマレスの自由度の高さに甘えた DB 設計になってしまったことも事実です。基本は正規化を維持しながら Read と Write を使い分ける非正規化の設計や Firestore が提供している最低限のクエリをベースに高パフォーマンスがでる設計を考えるのは容易ではありません。

2 年間運用してきた上でいくつかのポイントを加味した設計方法やルールなどがようやくできてきました。いまはテックリードと共に DB の掃除とより良い形へマイグレーションも設計し始めていますので、それが無事に完走できた暁には知見を共有していきます。今後も Firebase/Firestore のコミュニティが広がることを期待しています。

Firebase Authentication

Firebase Authentication は導入がとても簡単で複数の認証要素を提供してくれる優れものです。しかし、Firebase Authentication はプロジェクト単位でしか管理することができず物足りないという問題も顕在化してきました。

GCP では Firebase Autentication をベースにエンタープライズ向けに Identity Platform を提供しており、Firebase Authentication の機能をラップし、さらにマルチテナントでテナント別にユーザー管理ができたり、SAML, OIDC などの多要素認証をサポートしているため、今後はそちらに移行していこうと進めています。

Firebase Authentication は導入の手軽さ、運用の楽さが売りですので、サクッと導入してみて Identity Platform に移行していく手段もあることを知ってもらえると嬉しいです。

GCP (Google Cloud Platform)

GCP を扱うメンバーが多かったことや初期に Firebase を選択する意思決定をしたことから弊社では GCP を採用しています。業界シェア割合を考えて AWS, Azure への移行も考えましたがインフラ移行はリソースの観点からもプロダクト開発を並行しておこなうのはあまりにも体力が必要なことや GCP のドキュメントがシンプルで読みやすいこと、プロダクト開発や運用支援ツールなどが十分揃っていることから今後も GCP を使用していく予定です。

以下にキカガクで使用しているサービス概要を記載しておきます。

サービス 説明
App Engine 一部アプリのデプロイ
Cloud Run 一部アプリのデプロイ
Cloud Build CI/CD を構成(GitHub と連携)
Cloud Functions バックエンドで一部使用
Cloud Storage HTML, 画像, json ファイルなどを管理
Identity-Aware Proxy 開発環境で Google アカウントを紐付けてアクセス制御

まだまだ使用しているサービスは多くありますが、主要サービスはこちらになります。基本はサーバーレスアーキテクチャで構成し、少ないエンジニアでオペレーション負担の最小化やスケーラビリティを考慮したサーバーレスアーキテクチャを積極的に採用しています。

GKE を採用していない理由

GKE(Google Kubernetes Engine) の技術調査もおこないましたが、現状は必要ないという判断になりました。運用面で考えなければいけないことが多いことや Kubernetes の学習コストがかかること、現状の単純なアーキテクチャでは採用するメリットは小さいためです。 今回は採用しませんでしたが、エンジニア・チームの成長を考えて常に新しい技術には目を向け、挑戦していく組織でありたいと思っているので、新しい技術が好きなエンジニア大歓迎です。

悩んでいること

現状デプロイ先を App Engine を選択しており、Cloud Build との連携も簡単で GitHub への push, タグ付けをトリガーに CI/CD パイプラインを構築しており、非常に快適な開発生活を過ごしています。ただ、

  • デプロイ時間が長い
  • App Engine と Cloud Run の優越

デプロイ時間に関してはキャッシュを上手く活用したり、時間短縮に取り組んでいます。
また Cloud Run Always on CPU がリリースされ、非同期処理の実行環境としても採用できるようになったため、コンテナベースの Cloud Run で統一するという可能性も考えています。このあたり知見をお持ちの方がいらっしゃいましたら、ぜひご教示してもらえると嬉しいです。

データ分析基盤 / BigQuery

tech.kikagaku.co.jp

データ分析基盤は上記の記事をご覧ください。技術スタックとしては、

等で構成されています。

開発/コミュニケーションツール

社内での開発コミュニケーションツールとしては以下のツールを使用しています。

チケット管理や日々の進捗管理などエンジニアで閉じる内容に関しては GitHub で、プロダクト全体に関わるバックログの管理や議事録などは Notion、デザイン管理は Figma をそれぞれ使用しています。

弊社はフルリモートですので非同期コミュニケーションを大切にしており、ドキュメント化の徹底や MTG 前の議事録準備/事前共有の必須化などに取り組み、高い生産性を保ちながら開発が進められるように努めています。

おわりに

ここまで弊社の技術スタックを紹介しました。スモールチームで全員がフルスタックを基本とした構成を採用基準にした技術選定になっています。しかし、今後も新しい技術を導入する可能性は常に念頭においており、NestJS や GraphQL の調査・検証も未来を見据えて進めています。

キカガクでは何よりもエンジニアが楽しいと思える環境の提供とユーザーに価値が届けるスピードを優先し、これからも意思決定していこうと考えています。

今回詳細を省いた内容に関しましても、後日公開していく記事で書いていく予定ですので、今後の記事を楽しみに待っていてください。

ありがとうございました。

www.wantedly.com www.wantedly.com www.wantedly.com