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
290
1
Share
大規模サービスにおける レガシーコードからReactへの移行
React Tokyo フェス 2026 スポンサーセッションの発表資料です。
MagicPod
February 28, 2026
More Decks by MagicPod
See All by MagicPod
プログラミング不要! テスト自動化における生成AI使いこなし術
magicpod
1
150
今日から始められるテスト自動化 〜 基礎知識から生成AI活用まで 〜
magicpod
1
220
昨年の開発まとめ&今年の展望 2026
magicpod
0
340
【NTTドコモ様】ドコモで実践するMagicPod活用による 開発の効率化と付随して得られたもの
magicpod
0
440
MagicPodオンボーディング 導入の流れと導入初期によくある質問
magicpod
0
120
MagicPod Autopilot開発者Q&Aセッション
magicpod
1
110
AIを活用した自動サービス MagicPodのご紹介
magicpod
0
67
ノーコード × 生成AIの MagicPod Autopilotを使ったE2Eテスト生成
magicpod
0
710
ブランチ機能でQAチームのコラボレーションを加速しよう
magicpod
0
410
Other Decks in Technology
See All in Technology
Babylon.js を使って試した色々な内容 / Various things I tried using Babylon.js / Babylon.js 勉強会 vol.5
you
PRO
0
250
AIにより大幅に強化された AWS Transform Customを触ってみる
0air
0
320
AI前提とはどういうことか
daisuketakeda
0
130
本番環境でPHPコードに触れずに「使われていないコード」を調べるにはどうしたらよいか?
egmc
1
190
マルチモーダル非構造データとの闘い
shibuiwilliam
1
180
すごいぞManaged Kubernetes
harukasakihara
1
340
Babylon.js Japan Activities (2026/4)
limes2018
0
180
AWSで2番目にリリースされたサービスについてお話しします(諸説あります)
yama3133
0
130
建設的な現実逃避のしかた / How to practice constructive escapism
pauli
4
270
OCI技術資料 : ロード・バランサ 概要 - FLB・NLB共通
ocise
4
27k
OpenClawでPM業務を自動化
knishioka
2
390
ハーネスエンジニアリング×AI適応開発
aictokamiya
3
1.5k
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
698
190k
A better future with KSS
kneath
240
18k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
86
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
510
AI: The stuff that nobody shows you
jnunemaker
PRO
4
520
Crafting Experiences
bethany
1
110
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
64
54k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
510
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
780
Faster Mobile Websites
deanohume
310
31k
Evolving SEO for Evolving Search Engines
ryanjones
0
170
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
280
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