2022年ニコニコ生放送WebフロントのView事情

この記事は [ドワンゴ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/dwango) **19日目**の記事です。

ニコニコ生放送でフロントエンドエンジニアでビュー周りを担当している @misuken です。

今回は2022年現在のニコニコ生放送Webフロントのビューの部分に特化して、どのような変化があったのかを書いていきたいと思います。

[BCD Design]: https://qiita.com/misuken/items/19f9f603ab165e228fe1

## 技術セット

### 基礎

- React
- TypeScript
- Sass
- CSS Modules

### BCD Design

[BCD Design]は2019年にニコニコ生放送の開発から生まれたコンポーネント分類法。  
Atomic Designでモヤモヤしている方や、コンポーネントの分類に悩まれている方々から非常に高評価をいただいており、イチ推しとしてお気に入りにしているといった声も目にします。

[BCD Design]で分類すると、適切でないコンポーネント名が浮き上がってきたり、責務が合っていない実装が認識しやすくなるなど、lint的な効果も得られて質が向上します。

原理的にはコンポーネント分類に限らず、凝集度の高いドメインの世界に適合した技術がベースになっているため、コンポーネント以外の分野にも応用の効くものになっています。

適切な分類で開発を進めているため、ニコニコ生放送では激しく更新が入ってもほとんどコンフリクトが発生することはありません。

### Closet

2022年7月頃にニコニコ生放送の開発から生まれたSass利用前提のCSS設計です。

良いCSSの4原則と言われる「予測しやすい」「再利用しやすい」「保守しやすい」「拡張しやすい」を高度に満たしており、ニコニコ生放送ではCloset導入によって開発保守の効率と品質改善が大きく前進しました。

Closetは単純な仕組みながら、機能と見た目を完全に分離し、スタイルの堅牢なコンポーネント化を実現します。

スタイルに依存する責務をほぼすべてSass内に閉じ込められることから、JavaScriptの実装やディレクトリ構成からスタイルに依存した単語を消し去れるメリットもあります。(これにより[BCD Design]がさらに生きてきます)

責務管理、高凝集、VRTの観点からも優れており、スタイルが壊れる不安なく安心して変更できる点も加速度的なリファクタや品質向上に貢献しています。

ちなみに、Closetという名前は、クローゼットに用意しておいた衣装(スタイルのコンポーネント)を組み合わせたり、着せ替え感覚で手軽に扱えること命名されました。

Closetは2023年に詳細なドキュメントを公開する予定です。

## リポジトリの構成

2018年末にチームのメンバーが書いていた記事 [ニコニコ生放送がwebサービスを大人数で開発する際に辿ってきたフロントエンド アーキテクチャ](https://qiita.com/kondei/items/bdd725357b4dc9d7a8ab) の頃から基本的には変わっていません。

### 用語

#### VC (View Component)
いわゆる表示の責務を持つプレゼンテーションコンポーネント。  
APIや外部リソースと結合していないため、Storybookで静的に単体表示確認が可能。

#### CC (Container Component)

APIとの結合やドメインの状態管理を行い、VC用のPropsを生成するコンポーネント。

#### FES (Front-End Server)

バックエンドからページのための情報をかき集めるサーバー。  
CCが規定したPropsを渡して、Server Side Renderingする。

### 構成図

- 1つ1つはパッケージ
- パッケージを囲う四角形がモノレポ
- モノレポの抽象度によって層(依存関係)がある

![リポジトリ図-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/1ff6404c-5735-04ec-68cc-5128bd7d4431.png)

| 層         | リポジトリ             | パッケージ     | 説明                                                                      |
|-----------|-------------------|-----------|-------------------------------------------------------------------------|
| ライブラリ層    | NVC               | NVC       | 独自開発のUIライブラリ。<br />OSSレベルで汎用的なパッケージ。                                    |
| プロジェクト層   | NicoliveComponent | styles    | ニコニコ生放送に依存したSassの定数やmixinのユーティリティ。                                      |
|           |                   | stories   | ニコニコ生放送に依存したStorybookのユーティリティ。                                          |
|           |                   | VC      | ニコニコ生放送のスタイルを適用されたコンポーネント群。                                             |
|           |                   | CC        | MobXで実装された汎用的なドメインロジック。                                                 |
| アプリケーション層 | pc-program-watch  | VC/CC/FES | 番組視聴ページ。                                                                |
|           | pc-program-list   | VC/CC/FES | 一覧系ページ。<br />共通部分が多いので内部でさらにcommonとtop recent history ranking等複数パッケージに別れています。 |
|           | pc-program-create | VC/CC/FES | 番組作成ページ。                                                                |
|           | spweb             | VC/FES    | スマホ用ページ。<br />歴史的経緯でPC系と構成が違うが、VCの使い方は同じ。                               |

## ここ数年の問題

### チーム体制の問題

ここ数年、ニコニコ生放送ではアプリケーションチームの一人が一案件を担当し、その案件担当者がVC/CC/FESを一貫して実装するような体制になっていました。

![リポジトリ図-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/96d55e61-ae3e-c86d-e4e7-fb2cc6182421.png)

こうすることで案件を同時に走らせる並列係数は上がるのですが、案件担当者は案件を早く終わらせることに集中するため、どうしてもアプリケーション層でVCを実装する方向に向いてしまいます。

すると、本来はプロジェクト層で提供すべき定義、実装、スタイルがほとんど蓄積されず、似て非なるコンポーネントを作り続けることになります。
同じようなコンポーネントが量産されると、一つひとつのコンポーネントの品質を上げていくことはできません。

コンポーネント以外でも、あっちのリポジトリには定義があるけど、こっちのリポジトリには定義が無いのでハードコード、みたいなことが多発します。
こうして、プロジェクト層が薄くなってアプリケーション層が厚くなる、あまりよろしくない状況が続いていました。

VC担当(自分)が一人で整備しようとしても、十人程度がアプリケーション層で動いているととても追いつきません。
さらに、案件担当者は1〜3ヶ月に一回程度のペースでVCを触るので知見やスキルの共有も難しく、ビュー周りに強いメンバーの育成もできませんでした。

### スタイルの問題

開発当初はスタイル実装に強いエンジニアが1〜2人しかいなかったことに加え、実装に強いデザイナーさんがおり、デザインの質を高めるために実装しながら1px単位の調整を行いたいというデザイナーさんもいたことから、スタイルの実装はデザイナーさんが担当していました。

しかし実装に強いデザイナーさんが抜け、コードの規模が大きくなるに連れ、この体制には限界に達していきました。

1. エンジニアとデザイナーさんの実装への関心度の違い
    - デザイナーさんは実装よりもデザイン側に大きなウエイトがある
    - Sassのリファクタが後回しになり負債が雪だるま式に大きくなってしまう
    - リファクタの技術から教えていかないといけない
2. Sassのコード品質が維持できない
    - マジックナンバーが多い
    - コンポーネントの配置側と内側のスタイルが分けられていない
    - 循環依存や使われる側が使う側を知っている実装が散見される
    - 意図の読み取れない実装やそれに対するコメントが不足している
3. コンポーネント指向のスキルを持ったデザイナーさんがいない
    - デザインシステムが存在しない
    - 局所最適されたデザインが多く再利用性が低い
4. デザイナーチームが常に忙しい
    - 企画寄りの仕事も受け持っていて時間的な余裕がない
    - デザイナーチームのリソース管理で解決するのが難しい
5. スタイル実装がVCのリファクタの障害になる
    - HTML構造が変化してSassの変更が生じた際にスタイルの影響範囲がわかりにくく修正が困難
    - 逐一デザイナーさんにスタイルの意図を確認しないとリファクタが進まない
    - リファクタするほどデザイナーさんのPRレビューの負担が増えてしまう

特に5の問題が痛く、コンポーネントを整理したくてもスタイルが絡むとマージまでの時間がものすごく掛かるため手を付けにくく、コード全体の硬直化につながっていました。

### リポジトリを分ける意味

いっそのことアプリケーション層のVCを無くしてすべてプロジェクト層に移動してしまえばよいのではないかと感じるかもしれませんが、各アプリケーションがチームごとにリリースタイミングを制御したり、ビルド時間増加の問題などが絡んでいるため、そう単純にはいかない事情もあります。

例えば、プレーヤーのコンポーネントは視聴ページでしか使用しないので、大量の表示要素を含むプレーヤーを他の関係ないページと一緒に管理するのは合理的ではありません。

また、現在は常時案件をこなす必要があり、開発を止めて構成を変えたりリファクタをしたりするコストと、それに見合うリターンが得られるかといった確証もないため、度々議題には上がるのですが現在のリポジトリ構成のままになっています。

### 耐え忍ぶ日々

コンポーネントの旨味を十分発揮できない体制が続いても嘆いているわけにはいかないので、地道に時間経過とともに状況の好転に繋げる策を徹底していきました。

- **新規 - これ以上状況が悪くならないように**
    - 可能な限り自分が案件に入ってVC周辺の成長の方向性をコントロール
    - 実現コストと効果のバランスが釣り合わなさそうな企画要求やデザイン要求に対する交渉
- **保守 - 既存の非効率を軽減できるように**
    - アプリケーション層に散らばっていた同じ意味のコンポーネントをプロジェクト層に移動して統一
    - VRTの効果を高めるための表示パターン別ストーリーを追加
    - ReactやTypeScriptのバージョンアップやCSFなど、世の中の変化に対する追従
    - VC周りの機能強化やイケてなかった部分の改善、初期に作られた旧実装の改善
    - `strict: true`やlintなど、開発当初からの流れで緩かった場所の改善
- **将来 - 未来のコストを下げられるように**
    - Closet等、低コストでニコニコ生放送の要求をクリアできるアーキテクチャの検討
    - コスト意識やボトルネックの共有

難しいのは、常時案件が止められない状況で上記のアクションをバランス良く行い、案件のスケジュールを守りつつトンネルの出口を具体化するところでした。

それには優先順位が重要で「今これをやることによっていついつのコストをカットできる」のように、今日より明日 → 今週より来週 → 今月より来月 → 今年より来年に日々の作業が楽になること、将来失うはずだった時間をいつどのようにやると少ない投資で回収できるのか？(確度も高く)といったこと意識しながら、常に将来の時間確保につながる作業を連続で行えるよう徹底していきました。

こうすることで、時間経過とともに徐々に使える時間が増えていくので、最初に大規模で具体的な計画を建てずとも、少ない投資の積み重ねで大きなリターンを得られます。

また、人によってコスト意識に大きな差があり、そもそも危機感や問題意識を持てていなかったという場合もあったので、そういった認識の違いによっても改善に対して関心を持ってもらったり、理解を得られるかの大きな分かれ目になります。

正直かなりマンパワーを使ったところもあって大変でしたが、地道な努力の甲斐もあってか、全体の状況を好転させつつコスト効率や体制の問題に対する意識もエンジニアとデザイナーさんに浸透させていくことができました。

そしてようやく2022年、希望していたチーム体制へと変化を迎えることになりました。

## 2022年に変わったところ

- VCチームを新設
- VCチームがアプリケーションのVCまでを管轄
- スタイルもVCチームのエンジニアが実装
- アプリケーションチームはCCとFESに集中
- デザイナーさんはデザイン指示書の作成と表示確認

![リポジトリ図-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/5fb8286a-0544-9f9e-3977-559a106c4635.png)

### VCチームを再結成

今年になって、2016〜2017年頃に存在していたVCチームが再結成されました。
それと同時に各チームの責任範囲が見直され、各チームが本来関心のある作業に集中できるよう改善されました。

VCチームは現状2名体制ですが、今まで伝える機会がなかったHTMLやCSSの基礎知識から、実践的な知見を学ぶ時間も作れるようになり、認識を合わせながら円滑に開発できるようになっています。

### 責任範囲の変更

各案件のビュー部分をVCチームが依頼を受ける体制になったことで、VC全体を戦略的にコントロールできるようになりました。

アプリケーション層からプロジェクト層にコンポーネントを移動して統一したり、プロジェクト層のコンポーネントをリファクタしたり、最も効率の良いタイミングで計画的に行えます。

CSSのリファクタもデザイナーさんのレビューを待つこと無くVCチームのみで行えるため、気軽に行えるようになりました。

アプリケーションチームはほとんどVCを触る必要がなくなるので、ビューの煩わしい部分を考える必要がなくなり、CCとFESの作業に集中できます。

現在は方針を以下のように定めて作業を進めています。

- プロジェクト層では表示パターンをVRTで網羅する
- プロジェクト層に品質を担保したコンポーネントを増やす
- アプリケーション層では設置するだけで済むようにする
- アプリケーション層での作業を減らす
- 完全にアプリケーション層に閉じて依存するコンポーネントはアプリケーション層にあっても良い

アプリケーション層の実装を薄くすることで、VCチームのメンバーは、リポジトリを移動して作業するコストを減らせるなど、VCチームがプロジェクト層で集中して作業できるようにしています。

VC全般をコントロールできるおかげで、このような取り組み方をした上でVCチームが同時並行で複数の案件を受けても、改善が上回る状態を維持できるようになりました。

### エンジニアがスタイルを実装

もともと自身が論理的なスタイル実装(こういう意図だからこのプロパティを使い、プロパティはこの順番に並ぶ的な)についてよく考えていたこともあり、エンジニアがコードを管理できるようになってコード品質の改善が進んでいます。

ここで重要な役割を果たしているのが新しいCSS設計のClosetです。

Closetの仕組み的に、表示パターンごとの差の分析や、コード整理が捗るため、これまで各アプリケーションに散らばって複雑化していたスタイルを集約して簡単に整理できます。

学習コストも低く、VCチームのメンバーもすぐ対応できたのも良い点でした。

一時期カスタムプロパティを使うアプローチを試していた時期もありましたが、テーマのような一括で切り替えるものには向いている一方、細かく制御したいパターンでは複雑化したり大掛かりになるケースがあったので断念しました。

Closetは可読性が高く、書き味も良いので、ニコニコ生放送のように状態による表示パターンが複雑なサイトには特に相性が良いと感じています。

### エンジニアの育成

また、VCチーム発足時にCSSに不慣れなエンジニア向けのまとめも作成し、CSSのスキルアップにも力を入れました。

よく使用するプロパティや、プロパティごとの性質や分類、プロパティをどのように記述すると保守しやすいのか、といった重要な部分を重点的に学んでもらうことで、すぐに十分な品質のコードを書けるようになりました。

![エンジニア向けガイドライン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/dc69c432-8fb1-f9be-4c40-4d28c156b7ea.png)

### エンジニアとデザイナーさんの作業境界

VCチームとデザイナーさんの間で合理的な作業の境界を定めるため、以下の体制で合意を取りました。

- デザイナーさんはデザイン指示書の作成を行う
- デザイナーさんはPRで自動生成されるStorybookの表示確認のみ行う
- デザイナーさんはPRでコードレビューを行わない

デザイナーさんにはデザイン面の仕事に集中してもらい、将来的に余裕が出てきたらまた実装に戻ることも可能です。

スタイル実装が整理された状態で戻ってくれば、アーキテクチャがしっかりしている分、品質の守られたコードを書きやすくなると見込んでいます。

体制変更後、デザイナーさんからは「コードを書きたいメンバーもいるが、スタイル実装やコードレビューから離れたことで、他の仕事に集中できるようになった」との感想をいただき、関心の高い作業に力を注げるようになっていることがわかります。

最近はデザイナーチームがコンポーネント指向の考え方に変化してきているとの前向きな話も出てきていて、デザインシステムを作る計画もあるようです。VCチームはその未来に期待し、協力していきます。

## まとめ

- ニコニコ生放送の開発を通して新しい技術が生まれている
- リポジトリ構成は2018年頃から変わっていない
- 効率はリポジトリ構成を変えずともチーム体制によって大きく変わる
- 作業領域を関心を持つ技術単位に分けると改善が進みやすくなる(とは言え好き勝手やるのはNG)
- マンパワーは将来失うはずだった時間を効率よく回収できるところに使う(マンパワーを消費に使ってはダメ)
- 改善にはコスト意識やボトルネックの認識を合わせることが重要
- 論理的にスタイルを書ける人材(スタイル実装に強い人)の育成は大切

理想を言えばデザインシステムがあって、それをプロジェクト層でしっかり固められれば最も効率も品質も良く、一番楽なのは言うまでもないので、そういう段階までどのように持っていけるかが今後の課題です。

ビュー周りが好きな人ともっと改善したり良いものを作っていきたいので、そういった分野に興味のあるエンジニアさん、デザイナーさんがいたらぜひ一緒にお仕事しましょう。

## 余談

長々と書いてまいりましたが、 このような地道な改善やチーム体制の変化により、以前はなかなか手を付けられなかった部分でも、VCチームで完結できるならコストに見合うから着手可能といった部分も増えてきました。

そのため、エンジニア主導でユーザーさんの目に見える形で改善されたものも結構あります。

そういった変化が影響してかわかりませんが、 ユーザーさんから「最近いろいろ機能が追加されたり改善されている」と声をいただくこともあり、大変うれしく思っております。

しかし、エンジニアとしては、もっと当たり前のことを当たり前にできないといけないところも把握していますし、まだまだ改善したいところはたくさんあるので、全然満足しているわけではありません。

今後もユーザーさんにより快適に楽しんでいただけるサービスにするべく、精進してまいりますので、今後ともニコニコ生放送ならびにニコニコサービス全体を宜しくお願い致します。