Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
10周年を迎えたZEN Study Webフロントエンドの次の10年へ向けた工夫
Search
tris
May 25, 2026
Programming
70
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
10周年を迎えたZEN Study Webフロントエンドの次の10年へ向けた工夫
TSKaigi 2026 スポンサーセッション
https://2026.tskaigi.org/talks/85
tris
May 25, 2026
More Decks by tris
See All by tris
TypeScript だけを書いて Tauri でデスクトップアプリを作ろう / Tauri with only TypeScript
tris5572
2
3.3k
Other Decks in Programming
See All in Programming
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2k
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
4
2.5k
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
170
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
380
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.8k
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
140
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
600
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
180
FreeBSDでZabbixを動かす
kenkino
0
300
GKE で Pod の見方を変えたら、スケールアウト時の挙動を真に捉えられた話
stkk
0
130
XHTMLが残したもの
yosuke_furukawa
PRO
2
810
Featured
See All Featured
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
410
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.5k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
420
The Spectacular Lies of Maps
axbom
PRO
1
1k
Are puppies a ranking factor?
jonoalderson
2
3.9k
Done Done
chrislema
186
16k
We Have a Design System, Now What?
morganepeng
55
8.3k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
300
The SEO Collaboration Effect
kristinabergwall1
1
570
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
530
WENDY [Excerpt]
tessaabrams
14
39k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
350
Transcript
10周年を迎えた ZEN Study Webフロントエンドの 次の10年へ向けた工夫 株式会社ドワンゴ 教育事業 (小松) 2026/05/23 TSKaigi 2026
スポンサーセッション
自己紹介 • ドワンゴ 教育事業本部 e-learningプロダクト開発部 ZEN Study Webフロントエンドセクション 小松(こまつ) • ここ2年ほど
ZEN Study の開発に従事 • 趣味の1つ: ドライブ【距離ガバ】 日本本土の海沿いを走破+α 2 ニコニコ超会議の 配信に映り込む 不審なスタッフ
本セッションのサマリー • ドワンゴ教育事業とZEN Studyの概要 ◦ 事業・サービス ◦ これまでの10年のごく簡単な振り返り • 次の10年に向けてメンテナンス性を向上するために行なっている取り組みの一
部を、主にTypeScriptの観点から紹介 ◦ 外部とのやり取りの結果として、判別可能なユニオン型を活用し、状態を詳細にモ デリング (お昼休憩中なので、頭を使う難しい話ではなく、基本的な話をします) 3
ドワンゴの教育事業とは (1) • 主にN高グループとZEN大学に対して、教育に関するシステムを提供 N高グループ(N・S・R高) KADOKAWAとドワンゴが創るネットの高校 2016年4月開校(N高) 生徒数 3万人規模 ZEN大学
日本財団とドワンゴが創るオンライン大学 2025年4月開学 学生数 7千人規模 4
ドワンゴの教育事業とは (2) • 生徒・学生が直接使用するアプリや、学校の運営に関するシステムを提供 ◦ 学習アプリ ZEN Study ▪ 各学校向けだけではなく、一般向けにも月額課金で提供
◦ 教材作成・学校運営に関連するシステム 5
ZEN Study 10周年 🎉 • 2016年4月に「N予備校」としてサービス開始 10周年記念サイト https://www.nnn.ed.nico/pages/10th_anniversary サービスの歴史 ドワンゴ教育サービス開発者ブログ
https://blog.nnn.dev/ 10年を技術面から振り返る記事 6
10年の歴史がある = 10年の積み重ねがある • 最初の構築が急ピッチで行なわれた ◦ N高の開校と同時にリリースする必要があった ▪ 期限が決まっている中で、完全新規プロダクトの構築が行なわれた ◦
開発スピードを優先した選択が行なわれた ▪ メンテナンス性の優先度は低かった • 複雑性が積み重なっている ◦ 新機能の追加 ◦ 対象となる学校の増加 ▪ S高・R高の開校、大学の開学 ◦ リファクタリングが追い付いていないコード 7
ZEN Study 関連の開発体制 • フロントエンドはプラットフォームごとに分かれている • バックエンドは別チーム 8
ZEN Study Webフロントエンドの主な技術スタック • TypeScript + React SPA ◦ (Reactを10年使っているサービスは古参と言えそう)
• TanStack Query • React Router • React Redux 9
ZEN Study Webフロントエンド 10年間の技術変遷 次の10年を見据えて、コードベースの改善を継続して行なっている 10
次の10年に向けて メンテナンス性を向上するための 取り組み(の一部) 11 判別可能なユニオン型を利用して、状態を正確にモデリングする
判別可能なユニオン型を利用する方法の概要 • 外部 API 呼び出しの結果は、成功/失敗のケースがある • それなら汎用的な Result<T, E> を使うのが良さそう
😊 ◦ みんな Result を好きすぎて無限に Result の話をしている • でも Result<T, E> だけではツラいケースがある 😰 ◦ ローディング状態をどう表現する? ◦ エラーの中身をどうやって分ける? ◦ 使う側(コンポーネント)で細かい判定が必要で扱いにくい? ⇩ 判別可能なユニオン型を利用して、状態を正確にモデリングする方法を採用 (本質的には、外部への依存と内部実装とを切り分けている) 12
パターン1. コンポーネントで直接データを取得する • 🔥 データ取得と表示の責務が分離されていない • 🔥 コンポーネントのテストが大変 ◦ 通信をモックする必要がある
13
パターン2. データ取得をカスタムフックに分離する • 👍 データ取得と表示の責務が分離された • 👍 コンポーネントのテストが楽になった ◦ 通信ではなくカスタムフックをモックすれば良い
• 🔥 コンポーネントでの表示のために相変わらず色々と気にする必要がある ◦ 例:ローディングの判定のために特定のフラグを見る必要がある 14
パターン3. 汎用 Result (neverthrow) を使ってみる • 👍 コンポーネントでの表示時に気にすることが減った ◦ 特定の値(フラグ)を元にした判定が不要
• 🔥 ユニオン型と Result の使い分けが必要 ◦ 成功/失敗は Result だが、それ以外はユニオン型なので扱い方が異なる 15 ローディング中は undefined を 返すこととする
パターン4. カスタムフックが返す型としてユニオン型を利用 • この方式を我々は採用 • 👍 データ取得などの外部とのやり取りと表示の責務がより分離された • 👍 数々の嬉しさがある(後述)
判別可能なユニオン 16
ユニオン型を使う嬉しさ (1) • コンポーネントで switch 文によって状態ごとに容易に出し分けられる ◦ 複数の値を元にした状態の判別が不要 ◦ データの取得状態/結果とコンポーネントの表示を明確に関連付けられる
• 網羅性チェックを行える ◦ パターン追加時の堅牢性が上がる 網羅性チェックを実施可能 switch 文により単純に出し分け可能 判別可能なユニオン 17
ユニオン型を使う嬉しさ (2) • データ取得成功時のみ値があることが型で保証される ◦ 値を取得できていない状態のときは、値にアクセスできない • SUCCESS のときのみ値がある •
LOADING や ERROR のときには値がない ERROR などの状態で 値にアクセスを試みると 型エラーになる 18
ユニオン型を使う嬉しさ (3) • エラーの状態を細かく表現可能 その1 ◦ 例:リロードによる復旧可否を分ける リロードしても意味がないエラーと リロードにより復旧できるエラーを 別の型にする
リロードボタンの表示を容易に出し分けられる 19
ユニオン型を使う嬉しさ (4) • エラーの状態を細かく表現可能 その2 ◦ 例:HTTPステータスコードからコンポーネントを分離 ▪ エラーコードへ依存しないので、REST API
から GraphQL へ切り替えるような 場合も、コンポーネントに手を入れる必要がない HTTPステータスコードを直接利用するのではなく、 エラー種別ごとに型を作って、ステータスコードに 依存しないようにする 20
ユニオン型を使う嬉しさ (5) • エラーの状態を細かく表現可能 その3 ◦ 例:追加読み込みを行う API/コンポーネントにおいて、初回読込み時のエラーと追 加読込み時のエラーを区別する ▪
状況によりエラーの表示方法を変えるのが容易(初回読込み時だとエラーペー ジ、追加読込み時だとスナックバー、など) ▪ 単純に useInfiniteQuery を使うより複雑になっているとも言えるが、何を 優先するかのトレードオフ次第 21
ユニオン型を使う嬉しさ (6) • 実現方法の切替をコンポーネントと分離可能 ◦ 例:状態(履歴など)をサーバーに保存して全クライアントで同期したいが、ひと まず暫定的にローカルストレージへ保存して最低限改善する ▪ まずは暫定対応として、ローカルストレージへ保存するカスタムフックを実装 ▪
バックエンドの準備が完了し次第、API 呼び出しによりサーバーへ保存するカ スタムフックを実装 ▪ この前後で、カスタムフックの型シグネチャ(特に成功/失敗を表す戻り値の ユニオン型)が変わらなければ、コンポーネントの実装ではこの切替を意識す る必要がない 22 Webフロントエンド バックエンド まずは暫定的に ローカル保存 バックエンドの準備完了後、 サーバーへ保存 コンポーネント 呼び出しの型シグネチャに変更がなければ 意識せずに切替可能
まとめ • ZEN Study は10周年を迎えることができた 🎉 • 10年の積み重ねを踏まえつつ、次の10年に向けて改善を重ねている • TypeScriptの強力な機能である、判別可能なユニオン型を活用して、データ取
得などの状態(外部への依存)を正確にモデリングすることにより、堅牢でメ ンテナンスしやすくできた • 他にも様々な工夫・改善を行なっています! 23 めでたし めでたし 🤟