Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
大規模サービスにおける レガシーコードからReactへの移行
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
MagicPod
February 28, 2026
Technology
0
10
大規模サービスにおける レガシーコードからReactへの移行
React Tokyo フェス 2026 スポンサーセッションの発表資料です。
MagicPod
February 28, 2026
Tweet
Share
More Decks by MagicPod
See All by MagicPod
昨年の開発まとめ&今年の展望 2026
magicpod
0
9
【NTTドコモ様】ドコモで実践するMagicPod活用による 開発の効率化と付随して得られたもの
magicpod
0
16
MagicPodオンボーディング 導入の流れと導入初期によくある質問
magicpod
0
82
MagicPod Autopilot開発者Q&Aセッション
magicpod
1
93
AIを活用した自動サービス MagicPodのご紹介
magicpod
0
56
ノーコード × 生成AIの MagicPod Autopilotを使ったE2Eテスト生成
magicpod
0
560
ブランチ機能でQAチームのコラボレーションを加速しよう
magicpod
0
350
MagicPodユーザーミートアップ 最新の開発まとめ&今年の展望
magicpod
0
530
MagicPodが描くAIエージェント戦略とソフトウェアテストの未来
magicpod
1
960
Other Decks in Technology
See All in Technology
Introduction to Sansan Meishi Maker Development Engineer
sansan33
PRO
0
360
OCI技術資料 : 外部接続 VPN接続 詳細
ocise
1
10k
AIに視覚を与えモバイルアプリケーション開発をより円滑に行う
lycorptech_jp
PRO
1
640
What's new in Go 1.26?
ciarana
2
270
AWS Bedrock Guardrails / 機密情報の入力・出力をブロックする — Blocking Sensitive Information Input/Output
kazuhitonakayama
2
190
Devinを導入したら予想外の人たちに好評だった
tomuro
0
670
Agentic Codingの実践とチームで導入するための工夫
lycorptech_jp
PRO
0
260
Claude Cowork Plugins を読む - Skills駆動型業務エージェント設計の実像と構造
knishioka
0
210
JAWS DAYS 2026 CDP道場 事前説明会 / JAWS DAYS 2026 CDP Dojo briefing document
naospon
0
100
Exadata Fleet Update
oracle4engineer
PRO
0
1.3k
社内でAWS BuilderCards体験会を立ち上げ、得られた気づき / 20260225 Masaki Okuda
shift_evolve
PRO
1
150
Windows ネットワークを再確認する
murachiakira
PRO
0
200
Featured
See All Featured
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
160
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
150
Darren the Foodie - Storyboard
khoart
PRO
3
2.7k
How to train your dragon (web standard)
notwaldorf
97
6.5k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
280
GitHub's CSS Performance
jonrohan
1032
470k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
63
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
110
The Cult of Friendly URLs
andyhume
79
6.8k
Mind Mapping
helmedeiros
PRO
1
110
Transcript
大規模サービスにおける レガシーコードからReactへの移行 React Tokyo フェス 2026 スポンサーセッション
Kosuke Takahashi 2021年外資系IT企業にエンジニアとして入 社。 2022年MagicPodにエンジニアとして入社。フ ロントエンドからサーバーサイド、運用等幅 広く経験。 MagicPod ソフトウェアエンジニア 自己紹介
AIが自動テストの作成からメンテナンスまでサポート。 効果的なテスト自動化で、開発全体の効率UPへ。 ノーコードテスト自動化ツール
目次 1.なぜReactに移行するのか? 2.課題の詳細 3.どのように移行するのか? 4.現時点の状況, まとめ
目次 1.なぜReactに移行するのか? 2.課題の詳細 3.どのように移行するのか? 4.現時点の状況, まとめ
認知コストが高く、保守性が乏しい HTMLファイル ファイル数: 139 総行数: 11160行 1番行数の多いファイル: 749行 CSSファイル ファイル数:
44 総行数: 13754行 1番行数の多いファイル: 1517行 JSファイル(jQuery) ファイル数: 47 総行数: 28381行 一番行数の多いファイル: 5397行 React移行前: 2022年2月 ×モジュール管理 😥 ×コンポーネント分割 😥
目次 1.なぜReactに移行するのか? 2.課題の詳細 3.どのように移行するのか? 4.現時点の状況, まとめ
$(“#area_1”).on(“click”, function (e) { // IDセレクタイベントの登録 ... } $(“#area_2”).on(“click”, function
(e) { // IDセレクタイベントの登録 ... $(“#area_1”).trigger(“click”); // 別セレクタのイベント発火 ... } $(“#area_1_1”).on(“click”, function (e) { // IDセレクタイベントの登録 ... e.stopPropagation(); // イベントの伝播をやめる ... } $(“.container”).on(“click”, function (e) { // クラスセレクタイベントの登録 ... } $(“#area_2”).addClass(“container”); // クラスの付与 課題1: イベント管理の複雑化 area_1_1 area_1 area_2 何でも書けてしまうが故に、メンテナンスが難しい 😥 認知コストが高く、変更容易性は低い 😥 レガシーコード(jQuery)
$(“#area_1”).on(“click”, function (e) { // IDセレクタイベントの登録 ... } $(“#area_2”).on(“click”, function
(e) { // IDセレクタイベントの登録 ... $(“#area_1”).trigger(“click”); // 別セレクタのイベント発火 ... } $(“#area_1_1”).on(“click”, function (e) { // IDセレクタイベントの登録 ... e.stopPropagation(); // イベントの伝播をやめる ... } $(“.container”).on(“click”, function (e) { // クラスセレクタイベントの登録 ... } $(“#area_2”).addClass(“container”); // クラスの付与 課題1: イベント管理の複雑化 どのHTML要素に、どのイベントが紐づいているかわかりやすい 😄 const AreaButtons = { funcA, funcB, funcC, }: prpps) => { return ( <button id=”area_1" onclick=funcA /> <button id=”area_2" onclick=funcB /> <button id=”area_1_1" onclick=funcC /> ) } レガシーコード(jQuery) React
global変数, var, letの乱用 😥 型がわからない 😥 /* global global_variable_a, global_variable_b,
global_c, function_a, promise_function_a */ /* exported variable_d, function_b, $element_a */ let variable_a = null; var variable_b = 0; const default_value = 100; ... function abc() { variable_a = “xxx”; if (varible_b == “yyy”) { varible_b = default_value + 10; } } ... abc(); 課題2: 状態管理の複雑化 レガシーコード(jQuery)
const, 型で安心 😄 /* global global_variable_a, global_variable_b, global_c, function_a, promise_function_a
*/ /* exported variable_d, function_b, $element_a */ let variable_a = null; var variable_b = 0; const default_value = 100; ... function abc() { variable_a = “xxx”; if (varible_b == “yyy”) { varible_b = default_value + 10; } } ... abc(); 課題2: 状態管理の複雑化 export const funcA = ( variable_a: number, fvariable_b: number, ) => { const default_value = 100; const variable_c = variable_a + fvariable_b; const [showSomething, setShowSomething] = useState(false); const funcABC = () => { if (variable_c > default_value) { setShowSomething(true); } }; return { variable_c, funcABC, }; }; レガシーコード(jQuery) React
課題3: UIロジックと状態管理ロジックの混在 UIを生成するロジックと、状態管理のロジックが混在することにより可読性と保守性が下がる 😥 テストが書きづらい 😥 function abc() { let
first_name = $(“#area_1”).data(“first_name”); if (first_name == “”) { first_name = “default_first_name”; } let last_name = $(“#area_1”).data(“last_name”); if (last_name !=) { last_name = last_name + “ san”; } $('<div/>') .data(“first_name”, first_name) .data(“last_name”, last_name) .appendTo('#area_1'); } レガシーコード(jQuery)
課題3: UIロジックと状態管理ロジックの混在 function abc() { let first_name = $(“#area_1”).data(“first_name”); if
(first_name == “”) { first_name = “default_first_name”; } let last_name = $(“#area_1”).data(“last_name”); if (last_name !=) { last_name = last_name + “ san”; } $('<div/>') .data(“first_name”, first_name) .data(“last_name”, last_name) .appendTo('#area_1'); } それぞれの関心ごとでファイルを分割することで、可読性と保守性が上がる 😄 テストが書きやすい 😄 // index.tsx const componentA = ({firstName, lastName}) => { const [updatedFirstName, updatedLastName] = useComponentA(firstName, lastName); return ( <div id="area_1"> <div data-first-name={first_name} data-last-name={last_name}></div> </div> ); } // hooks.ts export const useComponentA = (firstName: string, lastName: string) => { const updatedFirstName = firstName || "defaultFirstName"; const updatedLastName = lastName || "defaultLastName"; return { updatedFirstName, updatedLastName, }; }; React レガシーコード(jQuery)
目次 1.なぜReactに移行するのか? 2.課題の詳細 3.どのように移行するのか? 4.現時点の状況, まとめ
Django (+ jQuery) As-Is, To-be Django (+ React) S3 (React)
nginx nginx CloudFront あるべき姿 現状
Django (+ jQuery) As-Is, To-be Django (+ React) S3 (React)
nginx nginx CloudFront あるべき姿 現状 今回の範囲
Django側(HTML, jQuery) 移行するページやコンポーネントに対して、任意のidを適用する React側 付与したidから要素を取得し、それをReact rootとしDOMを構築する const domNode = document.getElementById(”rootA”);
const root = createRoot(domNode); root.render( <ComponentA/> ); 移行方法(静的) <div id="rootA"></div> HTML, jQuery React
Pub/Subで、動的なイベントをハンドルする react_main.jQueryEventHub.publish({ eventName: “ChangeEvent”, data: { message: “sampleMessage” } })
移行方法(動的) useEffect(<T extends GuidanceKeys>() => { const deviceAlertSubscription = jQueryEventHub.subscribe<{ message: string; }>('ChangeEvent', (event) => { const message = event.data.message; if (message == “sampleMessage”) { showMessage(message); } }); return () => subscription.unsubscribe(); }, []); HTML, jQuery React
機能フラグによる段階的リリース 完成したコンポーネントから即時リリース 少数ユーザーへ段階的に公開し、全ユーザーへの影響を最小化 E2Eテストによる品質担保 MagicPodを使用した自動テスト 複数ユースケースの検証 画像差分チェックによるスタイル崩れ検知 バグバッシュ チームで変更箇所周辺を探索的にテスト リリース戦略
目次 1.なぜReactに移行するのか? 2.課題の詳細 3.どのように移行するのか? 4.現時点の状況, まとめ
移行の現状 (jQuery → jQuery+React) HTMLファイル(index.tsx) ファイル数: 499 総行数: 63550行 1番行数の多いファイル:
1308行 CSSファイル(style.ts) ファイル数: 347 総行数: 22409行 1番行数の多いファイル: 432行 JSファイル(hooks.ts) ファイル数: 369 総行数: 47998行 1番行数の多いファイル: 2671行 HTMLファイル ファイル数: 139 総行数: 11160行 1番行数の多いファイル: 749行 CSSファイル ファイル数: 44 総行数: 13754行 1番行数の多いファイル: 1517行 JSファイル ファイル数: 47 総行数: 28381行 一番行数の多いファイル: 5397行 HTMLファイル ファイル数: 104 総行数: 7264行 1番行数の多いファイル: 959行 CSSファイル ファイル数: 31 総行数: 13554行 1番行数の多いファイル: 2468行 JSファイル ファイル数: 34 総行数: 28782行 1番行数の多いファイル: 7743行 レガシーコード レガシーコード React 2022年2月 2026年2月(新機能含む)
良かったこと 新機能を開発しやすい 1ファイルあたりの行数が抑えられている 可読性, 変更容易性が向上 チームや組織でデザインの基準を合わせられる コンポーネント管理, 再利用可能 テストコードが増える 主にロジック(hooks.ts)のテストが増える
保守性が向上 トラブルやバグが発生した時に、テストを書いて修正ができる AIの進化 今後、より簡単に移行が進められる可能性がある
苦悩・課題感 教育・キャッチアップコスト jQuery中心だったエンジニアの学習コスト 他チームへの教育・知識共有 レガシーコード移行の難しさ 仕様が曖昧な既存コードの存在 元のコードがレガシーだと、移行後のコードもレガシー 移行に伴う工数増加 既存コードの理解に時間を要する 肥大化したファイルの分割・移行コスト
ユーザーへのインパクト 単なる技術的な移行では、コストの割にインパクトが少ない ビジネスメンバーの理解を得づらい
AIが自動テストの作成からメンテナンスまでサポート。 効果的なテスト自動化で、開発全体の効率UPへ。 ノーコードテスト自動化ツール
特徴1:ノーコードでテスト自動化が可能 1 テストステップを作成 テスト結果と結果詳細画面への導線 画面上から テスト対象要素を選択 要素自動検出を開始 2 3 4
テスト対象アプリケーションに変更等があると、そのままではテストは失敗してしまいます。 MagicPodのAIはテストを自動で修復して実行を継続。実行後に修正案を提案します。 自動修復が働くと「要確認」 と表示されます ! 特徴2:AIによる自動修復でメンテナンス工数を低減
これからのテスト自動化:作成〜運用をAIがサポート MagicPod Autopilot ユーザーの指示に基づき、テスト を自動で作成します。既存テスト の修正などにも幅広く対応しま す。 画面の内容やテキストを理解し、 従来は人間が検証する必要があっ たテスト項目も自動化します。
UIに変更があった場合に、AIがテ ストケース側の修正を提案・修復 します。 AIアサーション AI自動修復 テスト作成 結果確認 テストメンテナンス MagicPodは、テスト作成のMagicPod Autopilot、結果確認のAIアサーション、 メンテナンスのAI自動修復と、AIの力で自動テストを幅広くサポート。
Autopilotのチャットから指示を出します。 Autopilotのチャット形式の入力欄に「***を行うテストを作成して」などの指示を 出すことで、Autopilotが自動で適切なテストを検討・作成し実行します。 AIによる自動テストの作成
結果が期待通りかどうか、AIが合否判定 「表示された商品がすべてクリスマス関連 のものであること」をAIで確認 ハロウィーン関連の商品が 表示されています! 整合性を確認するテスト ネットショップで、検索ワードに対して正しい商品一覧が表示されているかを確認する。 例 1 2
3 検索欄に「クリスマス雑貨」を入力 「検索」ボタンを押す Failed! Failed! クリスマス雑貨
None