ZEN Study Webフロントエンドの10年とこれから

はじめに

ZEN Study(旧N予備校)は2026年4月にリリースから10周年を迎えました。開発者ブログでは「10年の変遷」を辿る連載企画をお届けしてきました。最後のテーマは、「Webフロントエンド」です。

ZEN Study がオンライン学習サービスとして始まってから今日まで、多くのユーザーがこのアプリの上で学んできました。その裏側で、Webフロントエンドのコードも止まることなく姿を変え続けてきました。

10年という節目に、ZEN Study Webフロントエンドが歩んできた道のりのふりかえりと、これからの方向性についてお話します。この10年を貫くのは 「今できる最善のやり方を常に選び続ける」 という考え方です。

「全てを書き換え続ける」 ——4年前のふりかえり

ZEN Study の Webフロントエンドは、React と TypeScript で書かれた SPA です。今でこそ一般的な構成ですが、ここに辿り着くまでの道のりは平坦ではありませんでした。

この構成の背景については、berlysia 氏が4年前に書いた 「すべてを書き換え続ける。N予備校Webフロントエンド実装6年のあゆみ」 という記事にまとまっています。旧N予備校のリリースから6年の間に、タイトルが示すとおり書き換える選択を続けながら Rails view, Page.js + jQuery, flowtype, 等々を経て現在の構成へと変化してきました。

ユーザーやビジネスの要求、デザインや API・インフラの変更、ブラウザや Web 標準の進化、ライブラリの進化、品質要求の変化——Webフロントエンドには変更の要因が多くあります。そのため、変化を前提に、いつでも作り替えられる状態を保とう、というのが記事の結論でした。

そのための具体的な指針として、記事では次の方針を挙げていました。

  • 交換可能な作り
  • 全体を過剰に枠にはめない
  • 侵襲度合いの低い道具を選ぶ
  • デファクトスタンダードに近い構成を維持
  • 理解が容易で捨てやすい作りを維持

これらによって生まれる柔軟さが変化し続けるための土台になります。

そして最後に以下のように締めくくっていました。

今できる最善のやり方を常に選び続けられるように、これからも変化を続けていきます。

その後の4年間

この4年間で、私たち ZEN Study Webフロントエンド開発者は、いくつかの苦境を味わい、新たな取り組みを始めてきました。

コードベースもこの4年で大きく成長しました。プロダクトコードは約2.3倍、テストコードは約3.1倍、テストケース数は1,634件から4,103件へと増えています。(LLMによるコード解析・集計値です)

苦境

ライブラリのメジャーアップデートや移行の苦しみ

侵襲度合いの高い、つまり依存の範囲が広かったり強度が強かったりするライブラリの破壊的変更や移行は、大きなインパクトを伴いました。

React Router や TanStack Query、Storybook のメジャーアップデートをはじめ、Redux から TanStack Query への移行(4年前の記事にも書かれていて今はだいぶ進んでいる)、Jest から Vitest への刷新など、その内容はさまざまです。

依存の範囲や強度は、ランニングコストや利便性を考えて決定しますが、その重要度はそのサービスの特性によると考えています。そして、サービスの特性も時とともに変化します。

我々は、「ZEN Study は今後長く使われるサービスである」という特性を意識しています。そこを鑑み、ライブラリの破壊的変更や移行にも柔軟な作りにすることにコストを割いていきたいと考えるようになりました。

API 仕様と密結合した内部実装の苦しみ

サービスの拡大にも苦しみを伴うことがあります。

2025年には ZEN大学 というネットを活用した新しい4年制大学が開学されました。ZEN Study は、ZEN大学の学生が単位認定に必要な授業等の受講から課題の提出までを行う学習プラットフォームとなっています。

それ以前の ZEN Study には一般ユーザー向けとN高グループ生向けの学習機能が存在していましたが、そこへ、ZEN大学生向けの学習機能を追加していきました。

ZEN Study 上では高校と大学はおおむね同じように振る舞うものの、一部はデータモデルやメンタルモデルが微妙に異なり、既存の機能に新しいルールを追加する必要もありました。

このとき困ったのが、API の型が、実質的なフロントエンドのモデルになっていたことでした。この作りのため、「高校と大学のAPI仕様の微妙な差」を吸収するためのコストがかかりました。

新たな取り組み

外部 API 接続を抽象化する external-functions の導入

API 仕様の変更がフロントエンドに直接波及する密結合の状態を解消するため、フロントエンド独自のドメインモデルを導入しました。UI(React コンポーネントや Hooks)もコアロジックも、すべてこの独自モデルに依存させ、API 仕様に依存した通信処理を閉じ込め抽象化するレイヤーを設けました。これを external-functions と名付けました。

external-functions は、外界の変化を内側に持ち込まないための翻訳層です。古くから「アダプター」や「腐敗防止層」と呼ばれてきた、外部との境界に変換役を置く考え方を、私たちの文脈で実装したものに過ぎません。これは API 仕様だけでなく、axios などのライブラリ、HTTP などの特定のプロトコル、Web 標準 API など、内部実装とは変化の質が異なる手段全般(全てではない)を抽象化する役割も担っています。

external-functions の概念図

これは、4年前に語られた「変化を前提に、いつでも作り替えられる状態を保つ」という発想を踏まえると、「交換可能な作り」や「侵襲度合いの低い道具を選ぶ」といった方針をより強固に実践するための施策になっています。

CSS Modules への回帰

ZEN Study の Webフロントエンドでは、過去に CSS Modules から styled-components へと移行していました。2019年のことでした。

2025年に styled-components のメンテナンスモード移行が発表されましたが、それ以前からチーム内ではゼロ・ランタイムのライブラリへの移行について話し合われており、2025年末頃に CSS Modules へ移行することを決定しました。一周回って原点に戻ることとなりました。

CSS Modules の採用の決定要因は以下でした。

  • styled-components からの移植のしやすさ
  • 学習・参入コストの低さ(諸説あり)
  • Web 標準という普遍的な技術資産の獲得
  • ライブラリが抱えるメンテナンス課題のリスク回避
  • 仕様の安定性

流行り廃りの激しいライブラリよりも Web 標準に近い構成を選ぶことは、「侵襲度合いの低い道具を選ぶ」という4年前の方針に沿った選択です。置き換えは現在も継続中です。

Playwright による E2E テストの試験的導入

直近では、Playwright による E2E テストを試験的に導入しました。

背景には、サービスインから10年が経ち、オンデマンド動画教材やライブ授業といったコア機能の体験の見直しや使用技術の移行など、複雑な仕様・複雑な実装を伴う箇所の抜本的な改善が予定されたことがあります。これらの機能は、単体テストだけでは品質の担保に限界がありました。

E2E テストであれば、実際に動画を流したり配信したりしながらの結合テストが可能で、ブラウザ上での挙動もバックエンドとの連携部分もテストでき、複雑なコア機能のリグレッションを防止しながら変更を実現できます。

「試験的導入」としたのは、E2E テストの導入・保守運用の経験が乏しく、E2E テストにありがちな課題をクリアできない可能性を捨てきれなかったためです。いきなり開発プロセスへ大々的に組み込むのではなく、スモールステップで始めました。特に気にしていたのは、次の課題です。

課題概要 説明
テストコードの設計の課題 煩雑になりメンテナンス性を担保するのが難しくなりがち。複数人でのメンテナンスがしにくくなりがち。
テスト実行の安定性の課題 Flaky になりがち。
複数のテスト環境への対応の課題 多くのテスト環境があり、環境によってデータが不揃いで綺麗に整理ができない。
パフォーマンスの課題 実行に時間がかかりがち。
どのテストを実装するかの課題 サービス全体を薄く網羅する膨大な量のテストを実装したくなりがち。
テストの実行方法の課題 遅く膨大なテストに対して、簡単に効率良くテストを実行する手段がない。

そこでまずは、これらの課題を解決するための学びを得ることを主軸としました。あえてすべての課題を無視した実装から始め、少しずつ対策を施していき、ひとまず1つのコア機能改善に役立てるという実績を作りました。今後も改善を繰り返し、E2E テストをより有効に活用できている状態を目指していきます。

おわりに

Rails から React へ、flowtype から TypeScript へ、CSS Modules から styled-components へ、そしてまた CSS Modules へ。この10年で構成は何度も入れ替わってきましたが、その軸にあるのは 「今できる最善のやり方を常に選び続ける」 という考え方です。

そして、その最善を選び続けるための具体的な指針として4年前に挙げられた次の方針は、10年目の今もなお有効だと感じています。

  • 交換可能な作り
  • 全体を過剰に枠にはめない
  • 侵襲度合いの低い道具を選ぶ
  • デファクトスタンダードに近い構成を維持
  • 理解が容易で捨てやすい作りを維持

この4年間の取り組みは、いずれもこれらの方針を今の状況に合わせて実践し直したものでした。

  • external-functions の導入:外部 API やライブラリを独自モデルの裏に閉じ込め、「交換可能な作り」「侵襲度合いの低い道具を選ぶ」をより強固にした。そしてこれ以上のルールを強いてはおらず、「全体を過剰に枠にはめない」ことも維持した。
  • CSS Modules への回帰:流行り廃りのあるライブラリより Web 標準に近い構成を選び、「侵襲度合いの低い道具を選ぶ」「デファクトスタンダードに近い構成を維持」を実践した。
  • Playwright による E2E テスト:複雑なコア機能のリグレッションを防ぐことで、「交換可能な作り」を品質面から支えた。

技術もライブラリも、人も AI も移り変わっていきます。次の10年も、今できる最善のやり方を常に選び続けられるように、これからも変化を続けていきます。

ZEN Study Webフロントエンドの10年とこれから