2024年 | Communitioサーバーサイド技術スタック
こんにちは!株式会社コミュニティオで主にサーバーサイドの開発を担当しているエンジニアの竹田です。今回は弊社Communitioのサーバーサイドで採用している技術スタックについて紹介したいと思います。フロントエンド・バックエンド・コミュニケーションツールなどを含めた包括的な弊社の技術スタックは以下のサイトを参照ください。
Communitioのプロダクトの特性
Communitioは企業文化を変革するためのサンクスカード・サービスTeamStickerと全社配信サービス(NewCommunicator)を提供しています。
TeamStickerは社内での感謝・賞賛の文化を促進するためのサービスで社員同士がお互いに感謝・賞賛の気持ちを伝えることができます。日々の業務での協力に感謝したり、仕事への成果を称えるタイミングはユーザー個別に異なります。ミーティングの後に感謝の気持ちを伝える、お昼時間に午前中の協力に感謝するなどユーザーの利用時間は多岐にわたるためサーバーに対する負荷は分散される一方、安定した応答性が求められます。
NewCommunicatorは社内での情報共有を促進するためのサービスで社内の情報を社員に向けてMicrosoft Teams上で配信することができます。全社一斉配信で数万人規模のユーザーへの配信を行うことがあるためサーバーはスケーラビリティが求められます。
技術スタック
上記のプロダクト特性と開発者のスキルセットを踏まえてCommunitioでは技術スタックを選定しています。
TeamStickerの技術スタック
PlayFramework | ZIO |
---|---|
![]() |
![]() |
TeamStickerはScala + PlayFramework + ZIOで実装されています。 弊社の開発者がScala + PlayFrameworkでの開発経験があったため採用しました。Scalaは型安全性が高く関数型プログラミングをサポートしており大規模なアプリケーションの開発に適しています。PlayFrameworkはJava・ScalaでWebアプリケーション開発のための定番フレームワークです。情報量の多さがメリットになります。また開発者の多くが関数型プログラミングに興味を持っていたため2020年当時新しく開発されていたZIOを導入しました。ZIOはScalaの関数型プログラミングをさらに推し進めるためのライブラリで非同期処理を安全に扱うことができます。
サービス提供開始時はPlayFrameworkを使ってフロントエンド・バックエンドの両方を開発していました。UIの開発サイクルを短くするためフロントエンドはTypeScript + Vue2のSPAに移行し、現在PlayFrameworkはAPIバックエンドサーバーとしての役割を担っています。SPAに移行したことでフロントエンドとバックエンドの開発を分離することができ、フロントエンドとバックエンドのリリースを独立させる、 開発者がそれぞれの得意分野に集中できるようなり開発サイクルの短縮が実現できました。
ZIOは関数型プログラミングのコンセプトをベースに開発されたライブラリです。開発者フレンドリーを主眼に設計されておりType Classのような概念を理解する必要がないため、Scala初心者でも扱いやすいというメリットがあります。ZIOは非同期・並列処理を安全に扱うためリソース管理や並列処理のためのコンビネーターを提供しており、ScalaのFutureと比較してエラーハンドリングや処理の合成が容易であるため、安全に非同期処理の実装ができます。ZIOの導入前はScalazのEitherTとFutureを用いて実装していました。導入後はIDEの型推論が効きやすくなり開発体験が大幅に向上しました。 ZIOの導入開始時はバージョン1.0-RCでしたが開発が活発に進み性能や機能(特に依存管理の部分)が大幅に改善されたバージョン2がリリースされました。 バージョン1と2の間では破壊的な変更が多くサービスでもZIOを利用したコードが多くなっていたためバージョンアップが困難でしたがなんとかバージョンアップを行い現在ではバージョン2を利用しています。
NewCommunicatorの技術スタック
Azure Functions | Azure Cosmos DB |
---|---|
![]() |
![]() |
NewCommunicatorはスケーラビリティが求められるサービスです。弊社インフラはAzureを利用しており、Azure Functionsを利用してサーバーレスアーキテクチャを採用しています。当初ScalaでのAzure Functionsの開発を検討していましたが、Scalaの起動時間が長い、デプロイの容易さなどインフラとの親和性、CosmosDBなどAzureサービス利用のためのSDKサポートを考慮してScalaは不採用としました。インフラとの親和性とSDKサポートだけを考慮するとC#も選択肢にあがるかもしれませんが、フロントエンドはTypeScriptを採用しているためフロントエンド開発との相性を考えNode.js + TypeScriptを採用しました。
NewCommunicatorの前の配信サービスはDurable Functionsで実装していました。数万人規模のユーザーへの配信を想定した実装になっていなかったため期待した配信性能が出ず動作が不安定でした。Queue StorageやCosmosDBを利用してAzure Functionsで再実装しました。処理の中断やエラーハンドリングの堅牢制をあげるため関数型プログラミング用ライブラリfp-tsを導入しました。fp-tsは例外を型として表現できるためエラーハンドリングが抜け漏れなく行える一方、学習コストが高いため、最近ではZIOから派生したEffectライブラリが良い気がしています。
ところでTeamStickerサービス提供開始時はAWS上で開発を行っていました。ビジネス上の観点からAWSからAzureに移行しました。クラウドサービス間の引っ越しにつきましては弊社インフラ担当の記事をお楽しみにしてください。
API駆動開発
上記の通りフロントエンドはSPAを採用しフロントエンドとバックエンドはREST APIで通信しています。フロントエンドとバックエンドの開発をさらに疎結合にするため弊社開発チームではAPI駆動開発を行っています。 機能開発の始めにOpen API SpecでAPI仕様を定義、GitHub ActionsでOpen API SpecからAPIクライアントを生成、APIクライアントはnpmパッケージとしてプライベートリポジトリに公開します。フロントエンド開発者はAPIクライアントのパッケージをnpm経由でインストールしAPIクライアントを利用してバックエンドとの通信を行います。この仕組みによってAPI仕様(やり取りするデータ構造と振る舞いの契約)に対してフロントエンドとバックエンドが共通の理解を持ちつつ独立して開発を進めることができます。現在はMock Service Workerを利用してサーバーのモックを用意してフロントエンドの開発を進める方法を模索しています。
まとめ
Communitioのサーバーサイドの技術スタックについて紹介しました。Scala + PlayFramework + ZIOとNode.js + Typescriptの組み合わせを採用しておりAPI駆動開発を行っています。今後も技術スタックの選定を見直し、より良いサービス提供を目指していきます。
コミュニティオでは今後更に多くのお客様に高品質で価値あるサービスを提供していきたいと考えており、一緒に働いてくれる仲間を募集しています!
ちょっと話聞いてみたい、と思っていただけましたらカジュアル面談もしておりますのでお気軽にお申し込みください!
Discussion