開発未分類メモ
URLルーティング設計:クエリパラメータとパスベースの使い分け
結論
「同じデータの異なるビュー」を表現するならクエリパラメータ、「別々のコンテンツ」を表現するならパスベースを使う。
背景
人生計画シミュレーターを開発中、ナビゲーション状態をURLで共有できるようにしたいという要件が出た。
現在の画面構成:
- 表示タブ > サマリー
- 表示タブ > 支出詳細 > 生活費
- 入力タブ > 家族構成 > 子ども1 > 教育方針
これをURLでどう表現するか?
2つの選択肢
パスベース
/life-plan/display/summary
/life-plan/display/expense-detail/living
/life-plan/input/family/child1/education
クエリパラメータ
/life-plan?tab=display&l1=summary
/life-plan?tab=display&l1=expense-detail&l2=living
/life-plan?tab=input&l1=family&l2=child1&l3=education
使い分けの基準
| 観点 | パスベース | クエリパラメータ |
|---|---|---|
| 意味 | 別のページ・リソース | 同じページの状態 |
| SEO | 個別にインデックスされる | 同一ページとして扱われる |
| 適した用途 | ブログ記事、商品ページ | フィルター、ソート、ビュー切替 |
| 実装 | ファイル構造が複雑になりがち | 1コンポーネントで完結 |
パスベースが適しているケース
- ブログの各記事(
/blog/article-slug) - ECサイトの商品ページ(
/products/12345) - 検索エンジンに個別にインデックスさせたいページ
- それぞれが独立したコンテンツを持つ場合
クエリパラメータが適しているケース
- 検索結果のフィルタリング(
/search?category=books&sort=price) - ダッシュボードの表示切替(
/dashboard?view=chart) - 同じデータを異なる角度から見るツール
- アプリケーションの「状態」を共有したい場合
今回の判断
人生計画シミュレーターではクエリパラメータを採用した。
理由:
- サマリー、年次収支、支出詳細は「別々のコンテンツ」ではなく「同じライフプランデータの異なるビュー」
- 検索エンジンに個別ページとしてインデックスさせる必要がない
- 実装がシンプル(1つのページコンポーネントで状態管理)
実装方針
// Nuxtでの実装例
const route = useRoute()
const router = useRouter()
// URLからナビゲーション状態を復元
onMounted(() => {
if (route.query.tab) activeTab.value = route.query.tab
if (route.query.l1) selectedL1.value = route.query.l1
// ...
})
// ナビゲーション変更時にURLを更新
watch([activeTab, selectedL1, selectedL2, selectedL3], () => {
router.replace({
query: {
tab: activeTab.value,
l1: selectedL1.value,
l2: selectedL2.value || undefined,
l3: selectedL3.value || undefined,
}
})
})
想定ユースケース:家族でのURL共有
今回の設計で想定しているシナリオを補足しておく。
現在の状態
- クエリパラメータで表示状態(どのタブ・カテゴリを見ているか)を共有できる
- 入力データ(収入額、生活費設定など)はURLには含まれない
- データの永続化は未実装(将来的にはlocalStorageまたはサーバー保存)
想定シナリオ
- 夫がシミュレーターで自分の家族データを入力
- 「サマリー > 可処分所得」の画面を妻に見せたい
- URLをコピーして妻に送る
- 妻が同じ画面位置で開ける
ただし現状では、妻側にはデータがないため数値は表示されない。あくまで「どの画面を見ているか」だけが共有される。
将来の拡張
将来的にユーザー登録機能を実装する場合:
- ユーザー登録 → 家族データをサーバーに保存
- 家族招待 → 妻をユーザーとして招待し、同じ家族データを共有
- URL共有 → クエリパラメータで「どの画面を見ているか」を伝える
この構成でも、クエリパラメータによるナビゲーション状態の共有は有効。データの永続化とビュー状態の共有は別の問題であり、今回のクエリパラメータ設計は将来の拡張と矛盾しない。
まとめ
URLルーティングの設計は「このURLが何を表しているか」で決める。
- リソース(記事、商品、ユーザーページ)→ パスベース
- 状態(フィルター、ビュー、ナビゲーション位置)→ クエリパラメータ
迷ったら「検索エンジンにこのURLを個別ページとしてインデックスさせたいか?」と問いかけてみるとよい。