レガシーになってしまったアプリケーションのライブラリをどのようにアップデートしていったか？

こちらは、「レガシー」を保守したり、刷新したりするにあたり得られた知見・ノウハウ・苦労話 by Works Human Intelligence Advent Calendar 2022 の 4日目の内容として投稿させていただきます。

## この記事で説明したいことのサマリー 

「脆弱性の危険性があるライブラリのversion up 」で得た以下の知見について共有させていただきます。
 
* ライブラリのアップデートをする際にはきちんとリリースノートを追うことが大切 
* 技術的負債を可視化する手段の1つとして、アップデートが必要なライブラリの数を見える化をするといい
* あえて、今はアップデートをしない決断もあり (計画に入れる) 
 
## ざっくり状況の説明
 
### プロダクトを内製化がスタート

外部の開発会社さんに委託していたシステムを今年(2022年)から内製のチームで引き取って、開発することになりました。
 
ちょこちょこ設計やいわゆるプロジェクトマネジメント、PRレビューなどでプロダクトのコードについては触れていたもののきちんと向き合ったのは今年の夏頃が初めてでした。 
 
### 引き取った際のコードの状況
 
チームメンバー内でコードを見てみると、コピペされたコードやかなりversionの古そうなライブラリが利用されているなど技術的負債が結構なものになっていました。 
 
この負債の返済をしないと機能追加やバグ修正の速度も落ちてしまうし、脆弱性も放置されたままになってしまう危険性があるので、技術的負債の返済をまずチームで行おうという決定をしました。

※ ビジネスサイドでも技術的負債の深刻さをご理解下さって、チームの工数を返済にあてることに共感を示してくれたのでとても心強かったです! 開発チーム一同感謝しています！ 
 
### 技術スタック 
#### 言語 
Javascript 

#### 主なフレームワーク・ライブラリ 

* React + react-router (Client-side rendering (CSR)の構成)
* express 
* Sequelize (O/R マッパー + マイグレーション管理)  

## 技術的負債の解消として取り組んだこと 

技術的負債の解消が必要な内容は多岐にわたっていたのですが、最初に以下の3つを中心に取り組みました。(今も継続して取り組んでいます。)
 
1. 脆弱性の危険性があるライブラリのversion up 
1. Javascript => Typescriptへのアップデート 
1. 開発環境のセットアップの改善 

今回は、この中の「脆弱性の危険性があるライブラリのversion up」で得た知見を共有します。
 
## ライブラリのversion upをどのように行ったか？ 
 
色々と反省もあるのですが、僕たちは以下のように「ライブラリのversion up」を行いました。
 
**[作業手順]** 

1. 脆弱性の危険性があるライブラリの可視化 
1. デグレードをしないためのテストがあることを確認 
1. ライブラリのversion upした際にプロダクトの改修が必要かどうかを判断
1. プロダクトの改修とライブラリのversion upをセットで行う必要がある場合は、チケットを起票してどのスプリントで改修するかの計画を立てる
1. プロダクトの改修が不要そうなライブラリは一括でversion up 
 
### 脆弱性の危険性があるライブラリの可視化 

まず、ライブラリが古いといってもどのライブラリのアップデートが必要なのか、またアップデートを放置するとよくないライブラリはどれなのかがぼんやりとしかわからなかったため、見える化する作業を行いました。

色々とツールはあると思うのですが、全社で導入している[脆弱性管理クラウド yamory](https://yamory.io/)をプロダクトに導入しました。 

※ 全社導入した経緯等は[こちら](https://yamory.io/blog/case-alphadrive/) 

Githubに連携するだけで、package.jsonなどの依存性管理ツールをスキャンしてライブラリの状況を可視化してくれるのでとても助かりました！ 
 
**[yamoryを利用して特にありがたかった機能]**
* 利用しているversionに脆弱性のあるライブラリの一覧
* 脆弱性のあるライブラリの数の遷移グラフ 
 
どのライブラリのアップデートが必要なのかを一覧化してくれるのもありがたかったですが、数がグラフでわかることでビジネスサイドにさっと状況を共有できるのがとてもありがたかったです。

### デグレードをしないためのテストがあることを確認 
 
ライブラリのアップデートはしたいのですが、アップデートによって既存のアプリケーションにバグが発生してしまうことを避けるために、既存動作保証のテストがあることを確認しました。 
 
もともと、開発を依頼していた開発会社さんがアプリケーションの主要な機能をカバーするテストケースを作成してくださっていたので、そちらを利用することでデグレード保証を行う方針にしました。 


### ライブラリのversion upした際にプロダクトの改修が必要かどうかを判断

ライブラリをversion upする際にメジャーアップデートを行うものについては、ライブラリのリリースノートの変更内容の一覧を確認し、deprecated となるメソッドなどがプロダクト内で利用されていないかを調査しました。
 

工数も限られていたので、マイナーversionのアップデートを行う場合はあまり細かく確認はせず気になるものだけ確認する方針にしていました。


###  プロダクトの改修とライブラリのversion upをセットで行う必要がある場合は、チケットを起票してどのスプリントで改修するかの計画を立てる 

ライブラリのアップデートをしたくても、影響範囲が大きいので今すぐはできない。
調査・変更の規模が大きいので一緒には行えないというケースがありました。 

僕たちのケースでは、Reactのv18へのメジャーversion upがそのようなケースに該当しました。

React v18 ではパフォーマンス改善のためにAutomatic batchingなどのいくつかの新機構が導入されています。


Automatic batchingによって、パフォーマンスが向上することは見込めるものの[Automatic batching for fewer renders in React 18: Does this break anything for Classes?](https://github.com/reactwg/react-18/discussions/21)にあるようにClass componentではデグレードのリスクがありました。

参考: https://github.com/reactwg/react-18/discussions/21

調査した結果、プロダクトのfrontendの実装では、Reactのclass componentが多用されており、このケースに該当するような記述も多数見つかりました。 
 
まずは、1つずつ該当するclass componentをhooksベースにリファクタリングしてからの方が影響範囲を限定してReactv18へのアップデートをできると考え、hook componentへの移行を優先することにしました。 

(Reactv18にアップデートしても、createRootへの置き換えをしなければ問題ないとは思うのですが、react-router, reduxなどの関連ライブラリもhooksでの利用を推奨していたため先送る決定をしました。) 

### プロダクトの改修が不要そうなライブラリは一括でversion up 
 
リリースノートの内容を調査した結果、ライブラリのversion upが問題なくできそうだと判断したものについて一気にアップデートを行い、事前に確認しておいたデグレードテストを実施しました。

## 結果、どうだったか？ 

影響度の小さい機能において、デグレードを1件出してしまいましたが、大きな混乱もなく約30%の脆弱性のあるライブラリのアップデートをすることができました! 

[yamory](https://yamory.io/)で脆弱性のあるライブラリの数の遷移が見えることで開発チームでも技術的負債解消されているなという実感が湧き、改善へのモチベーションを高く保つことができました。
ビジネスサイドにも同じグラフを共有したところ、「こんなに対応してくれたんですね」となり、目線の共有ができたのはよかったです！
 

## 学びと反省 

今回、ライブラリアップデートにあたって、OSSのリリースノートを色々と読んだのですが、ドキュメントが丁寧に整備されているもの・いないものがあり、ライブラリを採用する際にこの辺りのドキュメントが整備されていることはとても重要だなと学びになりました。

また、反省としては準備・調査をしたにもかかわらずデグレードを出してしまったことです。
デグレードが出た原因は、Sequelizeのメジャーアップデートでdeprecatedになったメソッドの影響範囲調査漏れでした。
 
deprecatedになったメソッド影響範囲調査の手法についてはチームで今後もっと改善させて、残りのライブラリについても計画的にアップデートしていこうと思います。