Reactは、仮想DOM(Virtual DOM)を活用して、高速かつ効率的なUI更新を実現するフレームワークとして知られています。しかし、仮想DOMが実際にどの程度のパフォーマンス向上をもたらしているかを測定し、その結果を最適化に活かすことは、React開発者にとって重要なスキルです。本記事では、仮想DOMの基本的な仕組みからパフォーマンス測定の具体的な方法、そしてその測定結果を基にした改善手法について詳しく解説します。Reactのアプリケーション開発において、仮想DOMを最大限に活用するための知識を深めていきましょう。
仮想DOMとは何か
仮想DOM(Virtual DOM)は、JavaScriptオブジェクトの形式で表現された軽量な仮想的なDOM構造です。これは実際のDOM(Document Object Model)を模倣したもので、Reactが高速なレンダリングを実現するための基盤となっています。
仮想DOMの役割
仮想DOMの主な役割は、UIの変更を効率的に管理することです。通常、DOM操作はブラウザのパフォーマンスに負荷をかけるため、大量の変更が頻発するとアプリケーションが遅くなる可能性があります。仮想DOMは、実際のDOMと仮想DOMの差分を計算して、必要最小限の操作だけを実際のDOMに反映させることで、この問題を解決します。
仮想DOMの仕組み
仮想DOMは次のように機能します:
- 仮想DOMの作成:Reactコンポーネントがレンダリングされると、仮想DOMツリーが作成されます。
- 差分の計算:新しい仮想DOMと古い仮想DOMを比較し、差分(diff)を計算します。
- 差分の反映:計算された差分だけを実際のDOMに反映します。
このプロセスにより、ReactはDOMの再描画を最小化し、パフォーマンスを向上させています。
仮想DOMの利点
- パフォーマンスの向上:最小限のDOM操作で、ブラウザへの負荷を軽減します。
- 予測可能な更新:差分計算に基づく更新により、複雑なUI変更も管理しやすくなります。
- デバッグの容易さ:仮想DOMの変更内容を追跡できるため、エラーの特定がしやすくなります。
仮想DOMは、Reactが効率的なUIフレームワークとして選ばれる理由の一つであり、開発者が動的なWebアプリケーションを構築するための強力なツールとなっています。
仮想DOMによるレンダリング最適化の仕組み
仮想DOMは、Reactアプリケーションのレンダリングを効率化するために設計されています。その中心的な考え方は「差分計算」にあります。これは、UI更新時に実際のDOM全体を操作する代わりに、必要な部分だけを効率的に更新する仕組みです。
差分計算 (Diffing Algorithm)
Reactは、新しい仮想DOMツリーと古い仮想DOMツリーを比較して変更点を特定します。このプロセスは以下のように進行します:
- ノード比較:ツリー内の各ノードを比較し、異なる部分を検出します。
- 変更の分類:検出された差分を次のように分類します:
- 追加:新たに生成されたノード。
- 削除:不要になったノード。
- 更新:内容が変更されたノード。
- 最適化された更新リストの作成:分類結果を基に、実際のDOMに反映する変更リストを生成します。
この差分計算により、Reactは必要な部分だけを操作するため、レンダリングのコストを大幅に削減できます。
バッチ処理による最適化
Reactは、複数の状態更新を一括して処理する「バッチ処理」を行います。これにより、個々の状態変更ごとに再レンダリングを発生させるのではなく、まとめて差分計算を行い、DOM操作を最小化します。
再レンダリングの制御
仮想DOMの最適化に加え、Reactでは以下の手法を使って再レンダリングを制御できます:
- shouldComponentUpdate (クラスコンポーネント):不要な再レンダリングを防ぐためのライフサイクルメソッド。
- React.memo (関数コンポーネント):プロパティが変更されない場合にコンポーネントを再レンダリングしないようにします。
- useCallback、useMemo:関数や値をメモ化して、不要な再計算や再レンダリングを防ぎます。
仮想DOMがもたらすパフォーマンス向上
- 大規模なDOM構造でも、必要最小限の更新だけを行える。
- 頻繁なUI変更でも滑らかな動作を維持できる。
- 開発者がDOM操作の最適化を手動で行う必要が減り、開発効率が向上。
仮想DOMは、効率的なUI更新を実現するためのReactの中核技術であり、動的なWebアプリケーションのレンダリングに最適化されたアプローチを提供しています。
レンダリングパフォーマンスを測定する理由
仮想DOMは効率的なレンダリングを提供しますが、その効果を最大限に引き出すためには、実際のパフォーマンスを測定し、ボトルネックを特定することが重要です。Reactアプリケーションのレンダリングパフォーマンスを測定する理由を以下に説明します。
アプリケーションのスムーズな動作を保証する
Reactアプリケーションは、複雑なUIを持つことが多く、ユーザーが頻繁に操作を行う場面が一般的です。例えば、フィルター機能を持つダッシュボードやリアルタイム更新を伴うチャットアプリでは、レンダリング性能がユーザー体験に直結します。測定を行うことで、以下を確認できます:
- 高頻度のUI更新がアプリケーション速度に影響を与えていないか。
- 大量のデータを扱うコンポーネントが最適に動作しているか。
パフォーマンスのボトルネックを特定する
アプリケーションが遅延を感じさせる場合、その原因は多岐にわたります。例えば:
- 再レンダリングが不必要に頻繁に発生している。
- 重い計算処理がメインスレッドを圧迫している。
- コンポーネントのツリー構造が複雑で、更新に時間がかかっている。
測定を行うことで、どの部分が問題なのかを明確にし、適切な対策を講じることが可能になります。
ユーザー体験の向上
レスポンスの遅いアプリケーションは、ユーザー体験を損ない、離脱率を高める要因となります。特に、商業アプリや大規模なプラットフォームでは、パフォーマンスの向上が直接的にユーザー満足度と収益に影響を与えます。
効率的な開発プロセスを支援する
パフォーマンス測定は、開発チームにとって次のメリットをもたらします:
- 問題箇所が具体的に特定できるため、効率的な修正が可能。
- コード変更後の性能改善効果を数値で確認できる。
- アプリケーションの拡張に伴う潜在的な問題を事前に予測できる。
測定の指標
レンダリングパフォーマンスを評価する際には、次の指標が役立ちます:
- フレーム率 (FPS):画面更新が滑らかかどうかを測定。
- コンポーネントのレンダリング時間:各コンポーネントがレンダリングに要する時間。
- 再レンダリング回数:不要なレンダリングがどの程度発生しているか。
測定の重要性
Reactアプリケーションは仮想DOMによる効率的なレンダリングを備えていますが、実際のパフォーマンスが必ずしも最適化されているわけではありません。測定を通じて現状を正確に把握し、必要な改善を施すことで、アプリケーションの品質を向上させることが可能です。
Reactで使用可能なパフォーマンス測定ツール
Reactアプリケーションのレンダリングパフォーマンスを正確に把握するためには、専用の測定ツールを活用することが不可欠です。ここでは、React開発で利用できる代表的なパフォーマンス測定ツールを紹介します。
React DevTools
概要: React専用の開発ツールで、コンポーネントの構造や状態の確認、パフォーマンス測定が可能です。
特徴:
- Profiler機能: 各コンポーネントのレンダリング時間や再レンダリングの発生頻度を記録します。
- PropsやStateの確認: 各コンポーネントの現在の状態をリアルタイムで表示。
- 再レンダリングの可視化: コンポーネントがいつ再レンダリングされたかをハイライト表示します。
利用方法:
- React DevToolsをインストール(Chrome/Firefox拡張機能)。
- アプリケーションをブラウザで開き、「Profiler」タブを選択。
- 計測したい操作を行い、結果を確認。
Chrome DevTools
概要: Web全般のパフォーマンス測定に使用できるブラウザ組み込みの開発ツール。
特徴:
- Performanceタブ: ページ全体のレンダリング、スクリプト実行、DOM更新にかかる時間を記録。
- Memoryタブ: メモリ消費量やリークの検出に役立ちます。
- フレーム率測定: UIの滑らかさを評価するためのフレームレートを表示。
利用方法:
- Chrome DevToolsを開き、「Performance」タブを選択。
- 「Record」をクリックして測定を開始。
- 操作後に「Stop」をクリックし、結果を分析。
Web Vitals
概要: Googleが提供するパフォーマンス測定ライブラリで、ユーザー体験に影響を与える主要な指標(Core Web Vitals)を測定します。
特徴:
- LCP (Largest Contentful Paint): 主要コンテンツが表示されるまでの時間。
- FID (First Input Delay): 初回ユーザー入力への応答速度。
- CLS (Cumulative Layout Shift): レイアウトの安定性。
利用方法:
web-vitals
パッケージをインストール。- 測定スクリプトをReactアプリに組み込む。
- コンソールやアナリティクスツールで結果を確認。
React Performance API
概要: ReactのuseEffect
やuseMemo
と組み合わせて、レンダリングの発生タイミングをカスタムで測定する手法です。
特徴:
- 柔軟な計測が可能。
- 特定のコンポーネントや処理に特化して詳細なデータを取得可能。
利用方法:
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
const start = performance.now();
// レンダリングの終了タイミングを測定
return () => {
const end = performance.now();
console.log(`Rendering time: ${end - start}ms`);
};
});
return <div>My Component</div>;
}
その他のツール
- Lighthouse: Google提供のツールで、アプリ全体のパフォーマンス、アクセシビリティを測定。
- why-did-you-render: Reactコンポーネントが不要に再レンダリングされる原因を特定するライブラリ。
Reactアプリケーションのパフォーマンス向上には、これらのツールを適切に使い分けることが効果的です。測定結果を基に、適切な最適化を施すことで、高品質なアプリケーションを構築する助けとなります。
レンダリングパフォーマンスの測定手順
Reactアプリケーションのレンダリングパフォーマンスを正確に測定するには、適切なツールと方法を活用することが重要です。以下に、具体的な手順を解説します。
1. React DevToolsを使用した測定
React DevTools Profilerの設定:
- インストール:
- ChromeやFirefoxの拡張機能からReact DevToolsを追加します。
- Profilerを有効化:
- ブラウザでアプリケーションを開き、開発ツールを表示。
- React DevToolsの「Profiler」タブを選択。
操作と記録:
- Profilerタブ内で「Record」をクリック。
- アプリケーション上で測定したい操作を実行(例: ボタンをクリックしてUIを更新)。
- 操作が完了したら「Stop」をクリックし、結果を確認。
結果の分析:
- 各コンポーネントのレンダリング時間が一覧表示されます。
- 再レンダリングの発生頻度が視覚的に示されるため、不要なレンダリング箇所を特定できます。
2. Chrome DevToolsでの詳細な測定
Performanceタブを使用:
- Chrome DevToolsを開き、「Performance」タブを選択。
- 「Record」をクリックして測定を開始。
- アプリケーションで測定対象の操作を行い、「Stop」をクリック。
結果の確認:
- タイムラインに各フレームのレンダリング、スクリプト実行、DOM更新が表示されます。
- 「Flame Chart」を分析して、どの関数や処理がパフォーマンスに影響を与えているか確認します。
3. コード内でカスタム測定
特定のコンポーネントや関数のレンダリング時間を直接測定したい場合、performance.now()
を使用します。
実装例:
import React, { useEffect } from 'react';
function ExampleComponent() {
useEffect(() => {
const start = performance.now();
// レンダリング後の処理
return () => {
const end = performance.now();
console.log(`Rendering time: ${end - start}ms`);
};
});
return <div>Example Component</div>;
}
このコードは、コンポーネントのレンダリング時間をコンソールに出力します。
4. パフォーマンス測定ライブラリの活用
why-did-you-renderライブラリ:
- 再レンダリングが発生したコンポーネントとその理由を特定できます。
導入手順:
- ライブラリをインストール:
npm install @welldone-software/why-did-you-render
- アプリケーションに設定:
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
if (process.env.NODE_ENV === 'development') {
whyDidYouRender(React);
}
const MyComponent = React.memo(() => <div>My Component</div>);
MyComponent.whyDidYouRender = true;
export default MyComponent;
結果確認:
- 再レンダリング時に詳細なログがコンソールに出力されます。
5. 測定結果に基づく改善計画
測定が終わったら、次の点に注意して改善を進めます:
- 再レンダリングの頻度が高いコンポーネントをReact.memoで最適化。
- 重い処理をuseMemoやuseCallbackでメモ化。
- レンダリングツリーが深い場合、必要に応じて分割して管理。
これらの手順を繰り返すことで、Reactアプリケーションのレンダリングパフォーマンスを効果的に向上させることが可能です。
レンダリング最適化の実践例
Reactアプリケーションのレンダリング性能を向上させるためには、具体的な最適化手法を適用することが重要です。以下に、一般的な問題を解決するための実践的な最適化方法とそのコード例を紹介します。
1. React.memoを使用したコンポーネントのメモ化
課題: 親コンポーネントの更新により、子コンポーネントが不要に再レンダリングされる。
解決方法: React.memoを使用して、子コンポーネントの再レンダリングを防ぎます。
コード例:
import React from 'react';
const ChildComponent = React.memo(({ value }) => {
console.log('ChildComponent rendered');
return <div>{value}</div>;
});
function ParentComponent() {
const [count, setCount] = React.useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
<ChildComponent value="Fixed Value" />
</div>
);
}
効果:
ChildComponent
は、value
が変わらない限り再レンダリングされません。
2. useCallbackとuseMemoの活用
課題: 子コンポーネントに渡す関数や値が毎回新しく作成されることで、子コンポーネントが再レンダリングされる。
解決方法: useCallbackとuseMemoを使用して、関数や値をメモ化します。
コード例:
import React, { useState, useCallback, useMemo } from 'react';
function ExpensiveCalculation({ number }) {
const result = useMemo(() => {
console.log('Expensive calculation');
return number * 2; // 高コストな計算の例
}, [number]);
return <div>Result: {result}</div>;
}
function ParentComponent() {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(1);
const handleIncrement = useCallback(() => setCount(count + 1), [count]);
return (
<div>
<button onClick={handleIncrement}>Increment Count</button>
<button onClick={() => setNumber(number + 1)}>Increment Number</button>
<ExpensiveCalculation number={number} />
</div>
);
}
効果:
ExpensiveCalculation
内の計算は、number
が変わったときだけ実行されます。handleIncrement
は再生成されないため、子コンポーネントでの不要な再レンダリングを防ぎます。
3. 不要な再レンダリングの防止
課題: ステートの変更が全体の再レンダリングを引き起こしている。
解決方法: 状態を必要なコンポーネントに絞り込む。
コード例:
import React, { useState } from 'react';
function ChildComponent({ value }) {
console.log('ChildComponent rendered');
return <div>{value}</div>;
}
function ParentComponent() {
const [stateA, setStateA] = useState(0);
const [stateB, setStateB] = useState(0);
return (
<div>
<button onClick={() => setStateA(stateA + 1)}>Increment A</button>
<button onClick={() => setStateB(stateB + 1)}>Increment B</button>
<ChildComponent value={stateB} />
</div>
);
}
効果:
ChildComponent
はstateB
に依存するため、stateA
の変更では再レンダリングされません。
4. レンダリングの分割 (Code Splitting)
課題: 大量のコンポーネントを一度にレンダリングすることで、初期表示が遅れる。
解決方法: ReactのReact.lazy
を使用して、コードを動的に読み込む。
コード例:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
効果:
HeavyComponent
は必要になるまで読み込まれません。初期ロードが軽くなります。
5. 仮想化 (Virtualization) を利用した大量データの最適化
課題: 大量のデータをリスト表示すると、DOMのレンダリングが遅くなる。
解決方法: リストの仮想化ライブラリを使用します。
コード例:
import React from 'react';
import { FixedSizeList as List } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>Row {index}</div>
);
function VirtualizedList() {
return (
<List
height={400}
width={300}
itemSize={35}
itemCount={1000}
>
{Row}
</List>
);
}
効果:
- DOMに表示される項目数を制限することで、レンダリングコストを削減できます。
これらの最適化手法を組み合わせて使用することで、Reactアプリケーションのレンダリング性能を大幅に改善することが可能です。計測結果を基に最適化を施し、パフォーマンスの向上を実現しましょう。
仮想DOMと他のフレームワークの比較
仮想DOMは、Reactが効率的なUI更新を実現するために採用した仕組みですが、他のフレームワークも独自の方法でUIレンダリングを最適化しています。ここでは、Reactの仮想DOMと、Vue.jsやSvelteなど他の主要フレームワークとの比較を行います。
1. Vue.jsの仮想DOM
Vue.jsも仮想DOMを採用しており、Reactと似た仕組みを持っています。しかし、Vue.jsは追加の最適化を提供することで、効率性を向上させています。
共通点:
- 仮想DOMを使用して差分計算を行い、実際のDOM更新を最小限に抑える。
- 再レンダリングの頻度を削減するため、コンポーネントの依存関係を追跡。
相違点:
- Vue.jsはリアクティブシステムを導入しており、データ変更をリアクティブに追跡することで、変更された部分だけを効率的に再レンダリングします。
- Reactの仮想DOMは全体の差分計算を行うため、大量の変更がある場合はVue.jsよりパフォーマンスが劣ることがあります。
Vue.jsの利点
- リアクティブシステムにより、変更箇所をより正確に特定できる。
- 小規模プロジェクトでは、Vue.jsの軽量さが有利に働く。
2. Svelteのリアクティブアプローチ
Svelteは仮想DOMを使用せず、コンパイル時にリアクティブなコードを生成することで、より直接的なDOM操作を実現します。
特徴:
- 仮想DOMを使用しないため、差分計算のオーバーヘッドが発生しない。
- コンポーネントごとに生成される最適化されたコードを実行することで、パフォーマンスが非常に高い。
比較:
- SvelteはReactやVue.jsと異なり、ランタイムではなくビルド時に最適化を行うため、軽量で高速。
- Reactの仮想DOMは柔軟性が高く、動的なUI更新が頻繁な場合に強みを発揮。
Svelteの利点
- 初期ロード時間が短い。
- 仮想DOMのオーバーヘッドがなく、パフォーマンスが高い。
3. Angularのデータバインディング
Angularは仮想DOMを採用していませんが、ゾーン(Zones)とデータバインディングを活用してDOM更新を効率化しています。
特徴:
- Angularは、リアクティブなデータバインディングを使用して、UIと状態を自動的に同期。
- 差分計算の代わりに、変更検知を行うことでUIを更新。
比較:
- Reactの仮想DOMは大規模プロジェクトにおいて予測可能性が高く、柔軟性に優れる。
- Angularのデータバインディングは、複雑なデータ構造を扱う場合に便利。
Angularの利点
- 組み込み機能が豊富で、エンタープライズ用途に向いている。
- 仮想DOMの概念に依存せず、堅牢な更新ロジックを提供。
4. ライブラリの選択基準
仮想DOMを選ぶべきか、それとも他のアプローチが適しているかは、プロジェクトの要件に依存します。以下の基準が参考になります:
フレームワーク | 仮想DOM使用 | パフォーマンス | 適用対象 |
---|---|---|---|
React | あり | 高 | 柔軟性が必要なプロジェクト |
Vue.js | あり | 非常に高 | リアクティブなUIが多い場合 |
Svelte | なし | 極めて高 | 小規模で高速が求められる場合 |
Angular | なし | 高 | 大規模エンタープライズアプリ |
5. React仮想DOMの強み
Reactの仮想DOMは以下の点で依然として強力な選択肢です:
- 柔軟性: 仮想DOMは幅広いユースケースに対応可能。
- エコシステム: 豊富なライブラリやツールが揃っている。
- 学習コスト: 仮想DOMの仕組みを理解することで、他のフレームワークにも応用可能。
Reactの仮想DOMは、他のフレームワークと比較しても高い柔軟性と信頼性を持ち、動的で複雑なUIを構築するための優れた選択肢となっています。
仮想DOMに関するよくある誤解
仮想DOMはReactの主要な特徴の一つですが、その仕組みや効果について誤解されていることも少なくありません。ここでは、仮想DOMに関する一般的な誤解を解消し、その正確な理解を深めます。
1. 仮想DOMが常にリアルDOMより高速である
誤解: 仮想DOMを使用すれば、必ずリアルDOM操作より高速になる。
実際: 仮想DOMは、リアルDOMの操作を最適化するための仕組みであり、その差分計算にもコストがかかります。少量のDOM操作であれば、直接リアルDOMを操作する方が効率的な場合もあります。
補足: 仮想DOMは以下のような場面で効果を発揮します:
- 頻繁なUI更新が必要な場合。
- 更新対象が大規模なDOM構造の一部に限定されている場合。
2. 仮想DOMはすべてのパフォーマンス問題を解決する
誤解: 仮想DOMを使用すれば、Reactアプリケーションのすべてのパフォーマンス問題が解消される。
実際: 仮想DOMはレンダリング効率を向上させますが、アプリ全体のパフォーマンスを保証するものではありません。以下の要因もアプリのパフォーマンスに影響を与えます:
- 重い計算処理。
- 大量データの管理やリスト描画。
- ネットワーク遅延やリソースの読み込み時間。
3. 仮想DOMはReactにしか存在しない
誤解: 仮想DOMはReactの専売特許である。
実際: 仮想DOMはReactが広めた概念ですが、Vue.jsや他のフレームワークでも採用されています。また、Svelteのように仮想DOMを使用しないフレームワークも存在します。
4. 仮想DOMは常に必要である
誤解: 効率的なUI構築には仮想DOMが不可欠である。
実際: 仮想DOMは効率化のための一手段に過ぎません。プロジェクトの規模や要件によっては、仮想DOMを必要としないケースもあります。
- シンプルな静的Webページでは仮想DOMの利点はほぼありません。
- 仮想DOMの計算コストが上回る場合もあります。
5. Reactコンポーネントが仮想DOMに直接依存している
誤解: Reactコンポーネントは仮想DOMがなければ機能しない。
実際: Reactのコンポーネントは、仮想DOMとは独立したUI構築の単位です。React自体は仮想DOM以外の方法でも動作可能で、React NativeやReact Server Componentsでは異なるレンダリングアプローチを使用します。
6. 仮想DOMはすべてのパフォーマンス指標を改善する
誤解: 仮想DOMはCPU使用率やメモリ使用量など、あらゆるパフォーマンス指標を向上させる。
実際: 仮想DOMは主にレンダリングパフォーマンスを改善しますが、以下のような指標には影響が限られます:
- 初期ロード時間: 仮想DOMの実装自体が追加のコストとなるため、初期ロード時間が増えることがあります。
- メモリ消費: 仮想DOMのデータ構造を保持するために追加のメモリが必要です。
7. 仮想DOMは他の最適化手法と併用できない
誤解: 仮想DOMを使用している場合、他の最適化手法(メモ化やコード分割)は不要である。
実際: 仮想DOMの性能を最大限に引き出すためには、React.memoやuseMemo、useCallbackなどの最適化手法を組み合わせることが重要です。
8. 仮想DOMの内部動作を完全に理解しなくてもよい
誤解: 仮想DOMの内部動作は開発者にとってブラックボックスであり、理解しなくてもアプリを構築できる。
実際: 仮想DOMの動作原理を理解していると、不要な再レンダリングやパフォーマンス低下の原因を特定しやすくなります。
例:
- 子コンポーネントが意図せず再レンダリングされている場合、差分計算の仕組みを知ることで原因を特定できます。
まとめ
仮想DOMはReactアプリケーションの効率的なレンダリングを支える重要な技術ですが、すべての状況で万能ではありません。適切な理解と期待を持ち、他の最適化手法と組み合わせることで、その利点を最大限に活用できます。仮想DOMに関する誤解を解消することで、Reactの設計とパフォーマンスをさらに深く理解することができるでしょう。
まとめ
本記事では、Reactの仮想DOMがどのようにレンダリング性能を向上させるのか、その仕組みや測定手法、さらには他フレームワークとの比較や誤解の解消について詳しく解説しました。仮想DOMはReactの中核技術であり、動的なWebアプリケーションにおいて効率的なUI更新を実現します。
特に、パフォーマンス測定の重要性とツールの活用方法、最適化の具体例を理解することで、開発者は実際のアプリケーションにおいて問題を特定し、効果的な改善を行うことができます。また、仮想DOMに関する正確な知識を持つことで、Reactの可能性を最大限に引き出すことが可能です。
仮想DOMの性能を測定し、最適化を施すことで、ユーザーにとって快適な体験を提供できるReactアプリケーションを構築していきましょう。
コメント