こんにちは。データ連携チームでフロントエンドエンジニアをしている ushiboy です。
この記事では、2024 年 9 月入社でチームに参加した筆者が、データ連携プロダクトのフロントエンドのコードベースで行なった半年間の取り組みについてご紹介します。
SmartHR ではプロダクトや機能ごとにチームが編成され、各チームに 1 名~ 2 名程度のフロントエンドエンジニアが在籍しています。 組成されて間もないチームの場合、フロントエンドエンジニアが不在の場合もあります。
筆者が配属された時点でデータ連携プロダクトはすでにリリースされており日々開発が続いていましたが、これまでフロントエンドエンジニアは在籍しておらずバックエンドエンジニアが中心となって開発を進めていました。
その影響もあり、フロントエンドのコードベースにはいくつかの課題が存在していました。それらの課題とどのように向き合い、対応したかをまとめます。
既存のコードベースを読み解き、整理・リファクタリングしていく必要がある場面において、進め方の参考になれば幸いです。
オンボーディングとチームの期待値
配属後すぐに行なわれたオンボーディングのなかで、チーフエンジニアから「フロントエンドまわりを一度ちゃんと見てほしい」と相談を受けました。 これまでバックエンドエンジニア中心で進めてきたことから、フロントエンドについての知見がチーム内に少なく、不安を感じていたそうです。
チーフエンジニアからざっくりと要望された観点は次のようなものでした。
- 他のプロダクトのコードを参考に実装・拡張した部分について設計が適切か
- テストが不足しているため React コンポーネントのテストを中心に増やしたい
- サードパーティの SDK を利用している部分について設計が適切か
- コンポーネントの設計やエラーハンドリングについての設計が適切か
- 使用しているライブラリについて先を見据えた構成として適切か
これらを意識しつつ、現状把握から進めることにしました。
現状把握と課題整理
まずはコードベースの読み込みにとりかかりました。
コードベースを読み込んで「ここは直した方が良さそう」と思ったポイントをメモしました。 また、チーム内にフロントエンドの構成を俯瞰できる資料が存在していなかったため、コードやディレクトリ・ファイルの構成を読み解き、簡単な資料としてまとめました。 資料はチームメンバーにレビューしてもらい、認識のズレがないことを確認したうえで、正式なチーム資料として残しました。
当時のデータ連携プロダクトは他のプロダクトを参考に開発環境からベースとなるコードまで用意されていたので大きな問題があるという状態ではないものの、開発を進める中で責務を多く抱え込んでしまったコンポーネントがあったり、テストが不足している状態でした。それらに対応するにあたってまず次の大前提を決めました。
- すでに動いているコードなので、意図せず壊してしまうことは避けたい
- 改善対応がプロダクトとしての直近の機能追加・修正の進行を妨げないようにしたい
- 将来的にも機能追加・修正のスピードを維持できるような内部品質にしておきたい
そして、適切にテストがあり手を入れやすい状態のコードベースにすることを目標として次の対応を行なうことにしました。
- テストのカバレッジ取得できる状態に整備する
- 特に React コンポーネントの単体テストを追加する
- 既存の Lint エラーの解消と整備をする
- VRT(Visual Regression Testing)や E2E テストを導入する
- 責務を抱えすぎているコンポーネントをリファクタリングする
- 非推奨になった、または、先を見据えて移行しておきたいライブラリの依存を剥がす
どこから手をつけていくか優先順位を整理し、改善方針としてチームに合意を得て対応にとりかかりました。 優先順位は次の点を意識して整理しました。
- 「意図せず壊してしまう」を検知できるようになるまで手を出せないものは後回しに、検知する仕組みの準備は優先的に行なう
- リスクが低く短時間で対応可能なものは最優先で行なう
ここからは優先順に行なった対応について個別に見ていきます。
単体テスト環境の整備と React コンポーネントのテスト追加
もともと単体テスト環境としてVitestが導入されており、プロダクト内のユーティリティ関数用のテストで使われていました。 ひとまずテストでカバーされている範囲を可視化するために、カバレッジを取得できるように環境整備しました。この時点で計測したカバレッジ(Statements)は 1.9%でした。
React コンポーネントの描画を伴う単体テストは存在していなかったので、Testing Libraryを利用して環境を用意しました。 ちょうどデータ連携に権限管理の機能を新規実装することになり、画面の追加が発生して良い機会だったので機能の実装と同時にテストを追加しました。 チームとしてははじめてのテストの書き方となるため、実際のテストコードで書き方の例を示してチーム内に共有しました。
既存コードに対してはリファクタリングと並行してテストを追加していくことにしました。
Lint の整備
ESLint、Stylelint、textlint が導入されていましたが、いくつか警告とエラーが出る状態になっていました。 エラーはもちろんですが、警告も放置すると増えていくことに対して感覚が麻痺しがちなので原因となるコードをすべて修正し、Lint 違反のない状態にしました。
エラーは textlint で発生していましたが、当時 textlint が CI に組み込まれておらず検知できていなかったため CI に組み込み、検知できるようにしました。
E2E テストと VRT を導入
既存コードについて単体テストを追加するにはリファクタリングしたほうがよいが、リファクタリングをするにはテストが欲しいという状況から、先にざっくり全体の動作を確認する E2E テストを導入することにしました。
E2E テストの実現方法としては個人的に過去に実績があり、社内でも他プロダクトで利用されているPlaywright を使うことにしました。 環境を整備し、ログインからデータ連携の各機能の画面を開いて意図した画面が開けるかを確認するテストケースを用意して、デプロイ後に動くように CI に組み込みました。
また、社内に Chromatic を利用した VRT 導入の資料や導入を支援する GitHub Actions があったため、それを利用して VRT を導入しました。 もともとデータ連携でもStorybookが使われていたこともあり、環境整備だけで行なうことができました。 単体テストや E2E テストでは検知できないスタイル上の見た目の故障を検知できるようになりました。
リファクタリング
E2E テストや VRT で「意図せず壊してしまった」をある程度検知できる仕組みが用意できたので、既存機能のコードのリファクタリングに着手しました。
小さなコンポーネントから着手していき、単体テストを追加して動きを保証してからリファクタリングを進めました。
責務を複数かかえている大きなコンポーネントについては、まず細かく動作を確認できる一枚の大きな単体テストを用意し、テストが通ることを確認してからプロダクトコードをリファクタリングして責務を分割し、テストコードの方も徐々に細かい単体テストに分割していきました。
テストが困難なサードパーティの SDK に依存したコードは依存関係を整理し、SDK への依存部分をモックに差し替えてテストできるようにしました。
小さな単位でリファクタリングしてこまめにプルリクエストとしてマージしていき、徐々に単体テストでカバーできる範囲を増やしていきました。カバレッジは 72%程度まで上昇しました。
ライブラリの整理
テストで確認できる範囲が増えてきたので、非推奨となったライブラリの依存を剥がしたり、ライブラリのバージョンアップなどを行ないました。例えば次のようなものを対応しました。
- 独自実装していたヘッダーコンポーネントをSmartHR UIの AppHeader コンポーネントに置き換えて同じ体験となるように改善
- styled-components を廃止して Tailwind CSS へ乗り換え
- Next.js と React のメジャーバージョンをアップデート
- ESLint の V9 へのアップデート
これらの対応には動作確認の手間などでなかなか重い腰が上がらないものもありますが、ある程度テストで保証できる状態になったので着実に行なえました。
その後
各種テストを追加したことで、Renovate や Depandabotを利用したライブラリのバージョンアップの動作確認コストが削減されました。
また、テストとリファクタリングでフットワークが軽くなったことと、データ連携プロダクトのフロントエンドが他のプロダクトに比べて機能がシンプルであったことから、他のプロダクトへの展開を見据えた技術検証の実験にデータ連携プロダクトのフロントエンドのコードベースを活用しています。 例えば多言語化対応のライブラリ選定で Next.js の Pages Router のアプリケーションでの導入パターンとして実装し、資料として社内に共有などをしています。
おわりに
既存のコードベースに途中参加して改善を行なうのは多少不安がありましたが、改善のための取り組みに時間を使うことに理解のあるチームで少しずつ土台を整え、目標としていた改善を行なえました。
本記事が、似たような状況にある方々の一助になれば幸いです。
We Are Hiring!
プロダクトや機能の開発に加えて、コードベースの改善のための取り組みにも理解のある組織で働いてみたい方、是非カジュアル面談のお申し込みからよろしくお願いします。