ZEN Study バックエンドの 10年を振り返って

ZEN Study (旧 N予備校)が10周年を迎えるに辺り、バックエンドがどう変わってきたかを振り返ります。


黎明期:2015年〜2016年

N予備校は 2015年の2月にプロジェクトがスタートし、2016年の4月にリリースされました。
当時、私は中堅として途中から加わりましたが、熟練のベテラン達に、実力のある新卒が集められ、一年で一気に開発されたプロジェクトという印象です。

2016年7月に、ライブ授業、課金機能が追加され一般公開が行われました。 その後、管理ツールや KPI の収集/計算機能など、一通りの機能が一年で そろえられました。

2016年9月に、個人情報管理機能が加わり、ユーザ管理のマイクロサービスが追加されています。このマイクロサービスのみパフォーマンス重視の観点で Rails より軽量な Padrino ( Sinatra ベースの軽量フレームワーク) がフレームワークとして導入されています。

開発環境

  • CI は Drone のオープンソース版が使用されていました。
  • Docker 導入はまだ
    • 当時は Mac 上での native 開発がメインで、Windows 利用の開発者のみ Vagrant を用いていました。Docker はまだ用いられていませんでした。

マイクロサービス構成

フレームワークには、当時、特に人気があった Ruby on Rails が用いられ、マイクロサービス構成で開発されました。 2015年当時は、まだマイクロサービス構成の利用例や情報が多くなく、モノリス構成の方がよいという反対意見もありました。
リリース直前の人員増加の際の分業に適していたともに、現在に至っても、膨大になっていくコードが分割されていることによるメンテナンスのしやすさや、 リリース範囲を限定しリスクを限定できるメリットがあり、先見の明はあったかと考えます。

詳細は、ブログ記事 N予備校のマイクロサービス を参照してください。

初期のサーバ構成

Service V1

API Gateway となるマイクロサービス内の Rails 実装のサービス層として Service V1 がリリース時に設計されました。
API Gateway の責務を最小限とする方向で設計されています。

  • 責務は、ユーザ認証 + マイクロサービスとの Proxy
  • マイクロサービスのレスポンスをできるだけそのままクライアントまで返す設計
  • キャッシュ対象はマイクロサービスのレスポンス単位のユーザ依存データであり、保持期間は1分

成長期:2017年〜2018年

リリースして1年が経過しましたが、まだサービス規模は小さかった時期。 次の方向性として、ユーザが教材を作って共有する機能や、Adaptive Learning など、様々な方向性が検討されていました。

その中で、2018年4月に N高の必修授業を N予備校上で受講できるようにすることとなり、大きく方向性が定まることとなります。 当時のN高の必修授業は受講環境が貧弱で学生からの不満も多く、教材の質にも改善が求められていました。そのため、改善策として N予備校での受講が決まりました。

Service V2

必修授業対応では、コード、責務が大きく増えるため、API Gateway のサービス層の設計の刷新が行われました。

Service V1 は、API Gateway はできるだけ薄い層にしようという設計でしたが、責務が膨れ上がり、各種課題が生じていました。

  • API Gateway をマイクロサービスのオーケストレーション層として設計し直す
  • 必修授業での負荷増加に備えて、キャッシュの有効活用を可能にする

という目的で作られたのが Service V2 となります。

Service V2 の特徴

  • オーケストレーション
    • 各マイクロサービスのレスポンスを API Gateway 内で定義されたクラスオブジェクトに格納して処理。 クライアントへのAPI仕様を管理して Serialize しなおす。
    • 当時、マイクロサービスのAPIを変更すると、クライアントへのレスポンスが変わるという問題が何度か起き、 API 仕様はマイクロサービスとの依存をなくして API Gateway で管理する方針に変更。
  • 長時間のキャッシュの可能化
    • 各マイクロサービスの API を、ユーザ共通とユーザ依存に分割
      • ユーザ共通のデータは長時間のキャッシュが可能となる
    • マイクロサービスから Pub/Sub による更新通知を用意して、キャッシュを削除
    • Rails cache を wrap して、属性が object (別クラスのインスタンス)でもまとめてキャッシュ
      • クラス単位でバージョニングをし、キャッシュのバージョンが異なれば自動破棄

開発環境

  • Docker が導入され、Docker環境上での開発に移行
  • Kubernetes がインフラに導入されました。
  • Go 言語の導入検討
    • Go 言語の導入検討が行われましたが、Rails、 Node に次ぐ第3の言語でメンバーのメンテナンス負荷が高くなるということで見送られています。 ここで導入されていたら開発の方向性は大きく変わっていたかもしれません。

調整期:2019年〜2020年

サービスの責務が大きくなっていく中、開発人数は増えず少ないままで、色々なプロジェクトが計画され、中止されたものも多かった時期。

N高の生徒が、学校のアカウントでログインできるようにすることとなり、 認証周りが大きく変更され、ニコニコアカウントベースから独自のアカウント ( ZEN Study アカウント)への移行が行われました。 この結果、ニコニコ以外に、N高マイページ、Apple での OIDC 認証によるログインが可能になり利便性が向上しました。

また、大きなプロジェクトとして VR 教材対応が行われました。 外部連携用の認証基盤として OpenID Connect(OIDC)を採用し、そのための ID プロバイダー(IdP)機能がシステムに組み込まれ、 以後、各種機能提供や管理ツールの OIDC 認証によるログインに利用されています。

教員が生徒の受講状況の詳細を確認するための管理ツールである LMS の開発が検討され、プロジェクト自体は中止となりましたが、 OpenAPI 及び OpenAPI Generator によるクライアントの自動生成の導入、AWS Cognito、Elasticsearch の導入検討など新しい技術の導入検討が興味深かった覚えがあります。


変革期:2021年〜2022年

この時期は、組織が大きく変わり、開発メンバーの増員が一気に進み、各機能の作り直し(清書)が始まった時期となります。

メンバーの増員に伴い、利用フレームワークも見直しが行われました。 ZEN Study は引き続き Rails/Ruby メインで REST ベースとなりますが、 新しいサービスに関しては、別言語(型付き言語)の導入や GraphQL、gRPC の導入が行われています

以下の新しいプロジェクトがこの時期に始まり、現在は専用の部署に分離していっています。

  • 教材作成 => ZEN Import (NestJS、 GraphQL)
  • 生徒の受講状況閲覧 => ZEN Compass (NestJS、 GraphQL)
  • 教材管理マイクロサービス => 新教材管理マイクロサービス (Kotlin、 gRPC)
  • KPI、データ分析 => データ分析基盤

新教材管理マイクロサービスの詳細に関しては ブログ N予備校バックエンドでサーバーサイドKotlin移行を始めました を参照ください。

Service V3

教材周りのリファクタリングに伴い、API Gateway のサービス層の見直しが再度行われました。

Service V2 の課題として以下がありました。

  • キャッシュが複雑化して把握しにくい
    • Service V2 設計時は、キャッシュを有効活用することで、できるだけ内部のマイクロサービスの台数は抑え、主に、API Gateway の マイクロサービスのみを、スケーリング(サーバ増台)させる方針で、全体のサーバ台数を抑えることを考えていました。 実際は、複雑にキャッシュを最適化するより、内部のマイクロサービスも増やしてしまうケースが増えており、サーバコスト や API latency の改善より シンプルな設計が優先されるケースが増えてきていた
  • 各モデル取得に通信他の副作用が隠蔽されており、通信や副作用の存在がわかりにくい
  • サービスロジックとモデルが1つのクラスに含まれている
    • モデルの取得の中に、通信や副作用が隠蔽される設計となっており、わかりやすい面もあったが、APIを通じて、通信が全部で何回行われるのか、 どのような副作用があるのかがわかりにくい設計となっていた
  • ルールが統一されておらず様々な書き方ができてしまい、メンバー間で統一されていない

これらの見直しとして Service V3 が設計されました。

Service V3

  • Service ロジックと Model のクラスを分ける
    • 通信の有無が Service ロジックで明確になるようにする
    • キャッシュ機構は後日検討
  • OpenAPI Generator での自動生成された client library利用
  • 運用ルールを定めて書き方を統一

運用保守グループ

技術的な問い合わせ対応などの運用業務が増加するとともに、Rails、Ruby の更新他の middleware 更新などの保守業務も滞りがちと なっていた状況があり、専用のチームとして、運用保守グループが新たに立ち上げられました。


成熟期:2023年〜2025年

増員でチームも増え、開発体制の安定化とともに、サービスの利用者、責務も増え、 可用性、品質向上がより求められてきた時期となります。
大きな変更として、2024/8 に「N予備校」から「ZEN Study」にサービス名称変更が行われました。

開発環境

2024年に発生したサイバー攻撃からの復旧・刷新プロセスを経て、開発環境は劇的な変化を遂げました。

  • 各ツールが Cloud に移行した
    • GitHub が GitHub Enterprise から GitHub Enterprise Cloud に移行
    • Confluence が Confluence Cloud に移行
  • デプロイ Jenkins から GitHub Actions
  • チームタスク管理 Jira => GitHub Project

ZEN大対応

2025年4月開校の ZEN大学対応で、ZEN Study の責務が大きく増え、利用者が増えました。

開発期間が短く力づくで無理も大きかった必修対応の頃に比べて、 複数のプロジェクトに分けて管理され、 整然と進められ、部署としての成熟を感じています。

各マイクロサービスごとの管理ツールの新設

管理ツールには、利用者に応じた様々な要望があり、少人数で用いる簡易な管理ツールへのアプローチとして マイクロサービスごとの管理ツールを Rails で新設しています。

  • フォーラム管理ツール
  • 授業管理ツール

管理ツールが NestJS で新設される中、最新の Rails のメリットをあらためて確認したいという意図もあり、 デザインは簡易に Bootstrap で、工数少なく機能を迅速に提供する方針で試しています。


今後:開拓期 2026年〜

現在のサーバ構成

新しい10年に入り、以下を行っていく予定です。

  • 求められる可用性への対応
    • サービスに求められる可用性、 品質は増加してきており、開発のスピードを維持するためには工夫が必要となってきている
  • AI の導入/効率化
    • 特に、運用, 保守業務は定型的な物が多く、AI の導入を進めていきたいと考えています
  • 新しい基盤の開発
    • よりよい体験を目指して、新しい基盤を作っていきたい。
  • 古くなった基盤の刷新
    • 配信基盤などの刷新

バックエンドとして ZEN Study でよりよい学習環境を提供していくためにチームで頑張ってまいります。 今後にご期待ください。