Ch 02. 동적 라우팅과 파라미터
블로그의 게시글 상세 페이지를 떠올려 보겠습니다. 게시글이 100개라면 pages/blog/1.vue, pages/blog/2.vue... 이렇게 100개의 파일을 만들 수는 없습니다. 이럴 때 동적 라우팅을 사용합니다. 파일명의 일부를 대괄호로 감싸면 그 부분이 동적으로 변하는 파라미터가 됩니다.
단일 동적 세그먼트
파일명을 [파라미터명].vue 형식으로 작성합니다. pages/blog/[id].vue 파일을 만들면 /blog/1, /blog/42, /blog/hello 등 모든 경로가 이 파일 하나로 처리됩니다.
파라미터 값은 useRoute() Composable로 접근합니다.
<!-- pages/blog/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const { id } = route.params
</script>
<template>
<div>
<h2>게시글 {{ id }}</h2>
</div>
</template>
route.params는 URL 파라미터를 담은 객체입니다. 파일명에서 대괄호 안에 적은 이름이 그대로 키(key)가 됩니다. [id].vue이면 route.params.id로 값을 가져옵니다.
Catch-all 라우트
[...slug].vue 형식으로 파일을 만들면 하위 경로 전체를 하나의 파라미터로 받을 수 있습니다. /docs/guide/install처럼 깊이를 알 수 없는 경로를 처리할 때 유용합니다.
<!-- pages/docs/[...slug].vue -->
<script setup lang="ts">
const route = useRoute()
// /docs/guide/install → ['guide', 'install']
const slug = route.params.slug
</script>
Catch-all 파라미터는 배열로 반환됩니다. /docs/guide/install에 접근하면 slug는 ['guide', 'install']이 됩니다.
선택적 파라미터
파라미터를 반드시 입력하지 않아도 되는 경우에는 이중 대괄호를 사용합니다. [[id]].vue로 파일을 만들면 /profile과 /profile/42 둘 다 같은 파일로 처리됩니다.
pages/profile/[[id]].vue
→ /profile (id 없음, route.params.id = undefined)
→ /profile/42 (id 있음, route.params.id = '42')
선택적 파라미터는 상세 페이지와 목록 페이지를 하나의 컴포넌트로 처리하고 싶을 때 활용합니다. 파라미터가 있으면 특정 항목을 보여주고, 없으면 전체 목록을 보여주는 방식으로 작성할 수 있습니다.
파라미터 반응성
useRoute()로 가져온 route.params는 반응형 데이터입니다. URL이 /blog/1에서 /blog/2로 바뀌면 route.params.id 값도 자동으로 업데이트됩니다. 데이터를 파라미터 변화에 맞춰 다시 불러오려면 watch를 활용하면 됩니다.
<script setup lang="ts">
const route = useRoute()
watch(() => route.params.id, (newId) => {
// 파라미터가 바뀔 때마다 실행됩니다.
console.log('새 게시글 ID:', newId)
})
</script>