【インターンレポート】LINE証券アプリのパフォーマンス改善

こんにちは。京都大学工学部情報学科の太田(@ten986)です。技術職 就業型コースのインターンシップに参加しました。
インターンでは、フィナンシャル開発センターWeb開発室Front-endチームに所属し、LINE証券アプリのパフォーマンス改善をしました。
この記事ではインターン期間中の成果を紹介します。


LINE証券のパフォーマンス改善

LINE証券について

LINE証券は、LINEアプリ内にあるネット証券サービスです。
このアプリは React + TypeScript で実装されています。


計測方法

パフォーマンスの計測にはChromeのDevtoolを用います。
Performanceタブにて、遅い端末を想定したスロットリングを適用して動作させたり、Profileを取ったりすることができます。

今回の計測では、以下の設定を用いました。
CPUスロットリング:6x slowdown
Networkスロットリング:なし

遅い端末を想定したCPUスロットリングをしますが、通信速度はすでに優秀で、改善点が見当たらないため気にしないものとします。


問題点

LINE証券のサービス内に、ポートフォリオページがあります。



パフォーマンスの計測をすると、このページの動作が重いことに気付きます。
特に、タブの切り替えの処理に時間がかかります。
ポートフォリオページは3つのタブがあり、各タブでは数十個のアイテムのあるリストを表示します。
リストの描画は遅いことが知られており、タブの切り替えをする際にリストを描画するようになっていたため、重い処理となっていました。
よって、タブの切り替えの処理の改善を中心に、ポートフォリオページのパフォーマンス改善をすることを目標とします。


TruncatedText の改善

ポートフォリオページでは、TruncatedTextというコンポーネントを使用しています。
このコンポーネントは、範囲内に収まらない文字を、「…」で省略する処理をします。


この処理はuseEffect内でinsertAdjacentHTMLを用いて実装されていましたが、これが重い処理となっていました。
この処理は現在、cssのみでの処理が可能です。
そのため、TruncatedTextの処理をcssで置き換えました。


BeforeAfter

こちらは読み込み時のProfileです。
読み込み時には、リストの生成が起こります。
赤枠で囲っている部分がTruncatedTextの処理にかかっていたものです。
この処理が無くなったため、読み込みやタブの切り替え時のリスト生成が速くなりました。

タブの切り替えの修正

このポートフォリオページは、タブの切り替え時に毎回リストを描画しています。
リストの描画は1回で済むはずなので、この修正をします。

リストの再描画の防止

このページの描画では、表示中でないタブは、Loading画面を表示するようにしていました。
この影響で、1度表示したタブであっても、タブを切り替えると描画した要素がunmountされるようになっていました。これを、表示中でないタブも表示するように修正しました。

BeforeAfter

この修正によって、リスト上にあるswitcherによるタブの切り替えではリストの再描画がなくなりました。
しかし、スワイプによるタブの切り替えではリストの再描画が起こり、また初回の読み込みの負担が大きくなります。この点を修正していきます。


memo化

スワイプによるタブの切り替えではリストの再描画が起こる問題を修正します。スワイプ時の処理を追うと、
リストの描画に用いる変数が、中身が変わらないものの参照が変わっていることが分かります。
参照が変わるため、再描画が必要と判断されてしまいます。

根本的には、この中身が変わらないが参照が変わる原因を取り除くべきです。
しかしこれは難しいので、中身が変わっていなければ、以降のコンポーネントの更新をしない、という方針にします。

ReactではReact.memoを使用した最適化ができます。
これにより一定条件を満たすときには、コンポーネントの描画を飛ばす処理が実装できます。
React.memoの条件を「与えた変数がDeepEqualsを満たしている」としたコンポーネントを実装し、ポートフォリオページの必要な箇所に適用しました。
これにより、スワイプ時にもリストの描画はされず、初回の描画のみで済むようになりました。


描画の遅延

リストの再描画を防ぐ際に、初回の描画ですべてのタブのリストを描画するようにしたため、初めて描画されるまでの時間が長くなってしまいました。
これを修正します。

描画を少しだけ遅延させるコンポーネントを、window.requestIdleCallbackを用いて実装しました。
このコンポーネントを、最初に表示されるタブ以外に適用しました。
これにより、最初の描画では1つのリストの表示にかかる時間のみで済むようになりました。
残りのリストは、ブラウザがアイドル状態のときに描画されます。

BeforeAfter

その他

メインの業務以外に、インターン期間中にやったことを挙げます。


リモートでのインターン

今回のインターンは、コロナの影響で基本は自宅からリモートでの開催となりました。
期間中は、Zoom上での会議や勉強会に参加し、そこで進捗の共有などをしました。
インターン生と対面で会えない中で、「リモートお茶会」という名前の会が開かれました。
これは、Zoomで他のインターン生との交流を趣旨としていて、
同年代の同じような興味分野を持つ人との雑談ができました。
また、短期間ではあるものの、実際にオフィスに行く機会がありました。
オフィスの雰囲気を知れたり、チームの方々とお話できたりと、貴重な体験をすることができました。


Code Readability Session for summer intern 2020

全8回の「コードの可読性についてのプレゼンテーション」を受けました。
持続可能な開発に必要な「コードの可読性」について、「変数の命名」から「依存関係」まで幅広い話題について学びました。
日頃コードを書く時になんとなく考えることが明文化され、コードレビューの際になぜこのコードが悪いのか指摘するのにも役立つよい講義でした。

資料は公開されていますので、気になる方は是非読んでみてください!
https://speakerdeck.com/munetoshi/code-readability
https://engineering.linecorp.com/ja/blog/code-readability-vol5/


文章の書き方講座

インターン中に、「文章の書き方講座」を受けました。
「文章の書き方講座」では、わかりやすい文章の書き方を、いい例と悪い例とを交えて教わりました。
エンジニアとして技術的な文章を書く機会はよくあります。
例えばこの講座での知識は、このブログ記事を書く際にも参考にしました。
技術とは直接関係ないが大切な分野を学ぶ機会はあまりないので、この機会に学べてよかったと思います。


あとがき

LINE証券という大きなプロダクトのパフォーマンス改善は、大変ですが非常に面白い経験でした。
改善点を発見することが一つの大きなタスクで、どの箇所がどの方面で改善できるかを調査するのに非常に時間がかかりました。
これはなかなか体験することのできない貴重な経験だと思います。
興味のある方は是非エントリーしてみてください!

Related Post