app.vue만 사용하는 경우 vue-router는 포함되지 않습니다. 페이지 시스템을 강제로 사용하려면 nuxt.config에서 pages: true를 설정하거나 router.options.ts를 사용하세요.페이지는 Vue 컴포넌트이며 Nuxt가 지원하는 모든 유효한 확장자를 사용할 수 있습니다(기본값은 .vue, .js, .jsx, .mjs, .ts 또는 .tsx).
Nuxt는 ~/pages/ 디렉터리의 각 페이지에 대해 자동으로 라우트를 생성합니다.
<template>
<h1>Index page</h1>
</template>
// https://vuejs.org/guide/extras/render-function.html
export default defineComponent({
render () {
return h('h1', 'Index page')
},
})
// https://nuxt.com/docs/4.x/examples/advanced/jsx
// https://vuejs.org/guide/extras/render-function.html#jsx-tsx
export default defineComponent({
render () {
return <h1>Index page</h1>
},
})
app/pages/index.vue 파일은 애플리케이션의 / 라우트에 매핑됩니다.
app.vue를 사용하는 경우, 현재 페이지를 표시하기 위해 <NuxtPage/> 컴포넌트를 사용하는 것을 잊지 마세요:
<template>
<div>
<!-- 모든 페이지에서 공유되는 마크업, 예: NavBar -->
<NuxtPage />
</div>
</template>
페이지는 페이지 간 라우트 전환을 허용하기 위해 반드시 하나의 루트 요소만 가져야 합니다. HTML 주석도 요소로 간주됩니다.
이는 라우트가 서버 렌더링되거나 정적으로 생성될 때는 내용을 올바르게 볼 수 있지만, 클라이언트 측 내비게이션 중에 해당 라우트로 이동하면 라우트 간 전환이 실패하고 라우트가 렌더링되지 않는 것을 보게 된다는 의미입니다.
다음은 단일 루트 요소를 가진 페이지가 어떻게 보이는지 설명하는 몇 가지 예시입니다:
<template>
<div>
<!-- 이 페이지는 올바르게 하나의 루트 요소만 가지고 있습니다 -->
Page content
</div>
</template>
<template>
<!-- 이 주석 때문에, 이 페이지는 클라이언트 측 내비게이션 중 라우트가 변경될 때 렌더링되지 않습니다 -->
<div>Page content</div>
</template>
<template>
<div>This page</div>
<div>Has more than one root element</div>
<div>And will not render when route changes during client side navigation</div>
</template>
대괄호 안에 무언가를 넣으면 동적 라우트 파라미터로 변환됩니다. 파일 이름이나 디렉터리 내에서 여러 파라미터와 비동적 텍스트를 섞어서 사용할 수 있습니다.
파라미터를 선택 사항 으로 만들고 싶다면, 이중 대괄호로 감싸야 합니다. 예를 들어, ~/pages/[[slug]]/index.vue 또는 ~/pages/[[slug]].vue는 /와 /test 둘 다에 매칭됩니다.
-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue
위 예시에서, 컴포넌트 내에서 $route 객체를 통해 group/id에 접근할 수 있습니다:
<template>
<p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>
/users-admins/123로 이동하면 다음이 렌더링됩니다:
<p>admins - 123</p>
Composition API를 사용하여 라우트에 접근하고 싶다면, Options API에서 this.$route처럼 라우트에 접근할 수 있게 해주는 전역 useRoute 함수가 있습니다.
<script setup lang="ts">
const route = useRoute()
if (route.params.group === 'admins' && !route.params.id) {
console.log('Warning! Make sure user is authenticated!')
}
</script>
/foo/hello 라우트의 경우, ~/pages/foo.vue가 ~/pages/foo/[slug].vue보다 우선합니다. /foo와 /foo/hello를 서로 다른 페이지로 매칭하려면 ~/pages/foo/index.vue와 ~/pages/foo/[slug].vue를 사용하세요,.캐치올(catch-all) 라우트가 필요하다면, [...slug].vue와 같은 이름의 파일을 사용하여 생성할 수 있습니다. 이는 해당 경로 아래의 모든 라우트와 매칭됩니다.
<template>
<p>{{ $route.params.slug }}</p>
</template>
/hello/world로 이동하면 다음이 렌더링됩니다:
<p>["hello", "world"]</p>
<NuxtPage>를 사용하여 중첩 라우트를 표시할 수 있습니다.
예시:
-| pages/
---| parent/
-----| child.vue
---| parent.vue
이 파일 트리는 다음과 같은 라우트를 생성합니다:
[
{
path: '/parent',
component: '~/pages/parent.vue',
name: 'parent',
children: [
{
path: 'child',
component: '~/pages/parent/child.vue',
name: 'parent-child',
},
],
},
]
child.vue 컴포넌트를 표시하려면, app/pages/parent.vue 안에 <NuxtPage> 컴포넌트를 삽입해야 합니다:
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :foobar="123" />
</div>
</template>
<script setup lang="ts">
const props = defineProps({
foobar: String,
})
console.log(props.foobar)
</script>
<NuxtPage> 컴포넌트가 다시 렌더링되는 시점을 더 세밀하게 제어하고 싶다면(예: 전환을 위해), pageKey prop에 문자열이나 함수를 전달하거나, definePageMeta를 통해 key 값을 정의할 수 있습니다:
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :page-key="route => route.fullPath" />
</div>
</template>
또는 다음과 같이 할 수도 있습니다:
<script setup lang="ts">
definePageMeta({
key: route => route.fullPath,
})
</script>
경우에 따라, 파일 기반 라우팅에 영향을 주지 않는 방식으로 특정 라우트 집합을 그룹화하고 싶을 수 있습니다. 이를 위해, 괄호 - ( 및 ) - 로 감싸진 폴더 안에 파일을 넣을 수 있습니다.
예를 들어:
-| pages/
---| index.vue
---| (marketing)/
-----| about.vue
-----| contact.vue
이렇게 하면 앱에서 /, /about, /contact 페이지가 생성됩니다. URL 구조 측면에서 marketing 그룹은 무시됩니다.
앱의 각 라우트에 대해 메타데이터를 정의하고 싶을 수 있습니다. 이는 definePageMeta 매크로를 사용하여 할 수 있으며, <script>와 <script setup> 모두에서 동작합니다:
<script setup lang="ts">
definePageMeta({
title: 'My home page',
})
</script>
이 데이터는 이후 앱의 다른 곳에서 route.meta 객체를 통해 접근할 수 있습니다.
<script setup lang="ts">
const route = useRoute()
console.log(route.meta.title) // My home page
</script>
중첩 라우트를 사용하는 경우, 이들 라우트의 페이지 메타데이터는 하나의 객체로 병합됩니다. 라우트 메타에 대한 자세한 내용은 vue-router 문서를 참고하세요.
defineEmits 또는 defineProps(참고: Vue 문서)와 마찬가지로, definePageMeta는 컴파일러 매크로입니다. 이는 컴파일 시 제거되므로, 컴포넌트 내에서 이를 참조할 수 없습니다. 대신, 여기에 전달된 메타데이터는 컴포넌트 밖으로 끌어올려집니다(hoist).
따라서 페이지 메타 객체는 컴포넌트를 참조할 수 없습니다. 그러나 가져온 바인딩(imported bindings)과 로컬에서 정의된 순수 함수는 참조할 수 있습니다.
<script setup lang="ts">
import { someData } from '~/utils/example'
function validateIdParam (route) {
return route.params.id && !Number.isNaN(Number(route.params.id))
}
const title = ref('')
definePageMeta({
validate: validateIdParam,
someData,
title, // 이렇게 하지 마세요. ref는 컴포넌트 밖으로 끌어올려집니다
})
</script>
물론, 앱 전반에서 자체적으로 사용할 메타데이터를 정의해도 됩니다. 하지만 definePageMeta로 정의된 일부 메타데이터는 특별한 목적을 가집니다:
alias페이지 별칭을 정의할 수 있습니다. 이를 통해 동일한 페이지에 서로 다른 경로로 접근할 수 있습니다. 이는 vue-router 문서에 정의된 대로 문자열 또는 문자열 배열이 될 수 있습니다.
keepalivedefinePageMeta에서 keepalive: true를 설정하면, Nuxt는 페이지를 자동으로 Vue <KeepAlive> 컴포넌트로 감쌉니다. 이는 예를 들어, 동적 자식 라우트를 가진 부모 라우트에서 라우트 변경 간 페이지 상태를 유지하고 싶을 때 유용할 수 있습니다.
부모 라우트의 상태를 유지하는 것이 목표라면, <NuxtPage keepalive /> 구문을 사용하세요. 또한 <KeepAlive>에 전달할 props를 설정할 수도 있습니다(전체 목록은 여기를 참고하세요).
이 속성의 기본값은 nuxt.config에서 설정할 수 있습니다.
keylayout라우트를 렌더링하는 데 사용되는 레이아웃을 정의할 수 있습니다. 이는 false(레이아웃 비활성화), 문자열 또는 ref/computed가 될 수 있으며, 어떤 방식으로든 반응형으로 만들고 싶을 때 사용할 수 있습니다. 레이아웃에 대해 더 알아보기.
layoutTransition and pageTransition페이지와 레이아웃을 감싸는 <transition> 컴포넌트에 대한 전환 속성을 정의하거나, 해당 라우트에 대해 <transition> 래퍼를 비활성화하려면 false를 전달할 수 있습니다. 전달할 수 있는 옵션 목록을 보거나, 전환이 어떻게 동작하는지에 대해 더 읽어볼 수 있습니다.
이 속성들의 기본값은 nuxt.config에서 설정할 수 있습니다.
middleware이 페이지를 로드하기 전에 적용할 미들웨어를 정의할 수 있습니다. 이는 매칭되는 부모/자식 라우트에서 사용되는 다른 모든 미들웨어와 병합됩니다. 문자열, 함수(글로벌 before 가드 패턴을 따르는 익명/인라인 미들웨어 함수), 또는 문자열/함수 배열이 될 수 있습니다. 명명된 미들웨어에 대해 더 알아보기.
name이 페이지의 라우트에 대한 이름을 정의할 수 있습니다.
path파일 이름으로 표현할 수 있는 것보다 더 복잡한 패턴이 있는 경우, 경로 매처를 정의할 수 있습니다. 자세한 내용은 vue-router 문서를 참고하세요.
props라우트 params를 페이지 컴포넌트에 전달되는 props로 접근할 수 있게 해줍니다. 자세한 내용은 vue-router 문서를 참고하세요.
페이지에 커스텀 메타데이터를 추가하는 경우, 타입 안전한 방식으로 하고 싶을 수 있습니다. definePageMeta가 허용하는 객체의 타입을 보강(augment)하는 것이 가능합니다:
declare module '#app' {
interface PageMeta {
pageType?: string
}
}
// 타입을 보강할 때는 항상 무언가를 import/export 하는 것이 중요합니다
export {}
앱의 페이지 간 내비게이션을 위해서는 <NuxtLink> 컴포넌트를 사용해야 합니다.
이 컴포넌트는 Nuxt에 포함되어 있으므로, 다른 컴포넌트처럼 import할 필요가 없습니다.
app/pages 폴더의 index.vue 페이지로 가는 간단한 링크 예시:
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>
Nuxt는 navigateTo() 유틸리티 메서드를 통해 프로그래밍 방식의 내비게이션을 허용합니다. 이 유틸리티 메서드를 사용하면, 앱에서 사용자를 프로그래밍 방식으로 이동시킬 수 있습니다. 이는 사용자 입력을 받아 애플리케이션 전반에서 동적으로 이동시키는 데 매우 유용합니다. 이 예시에서는 사용자가 검색 폼을 제출할 때 호출되는 navigate()라는 간단한 메서드가 있습니다.
navigateTo를 await 하거나, 함수에서 반환하여 그 결과를 체이닝하도록 하세요.<script setup lang="ts">
const name = ref('')
const type = ref(1)
function navigate () {
return navigateTo({
path: '/search',
query: {
name: name.value,
type: type.value,
},
})
}
</script>
.client.vue 접미사를 붙여 페이지를 클라이언트 전용으로 정의할 수 있습니다. 이 페이지의 내용은 서버에서 전혀 렌더링되지 않습니다.
.server.vue 접미사를 붙여 페이지를 서버 전용으로 정의할 수 있습니다. vue-router에 의해 제어되는 클라이언트 측 내비게이션을 사용하여 이 페이지로 이동할 수는 있지만, 자동으로 서버 컴포넌트로 렌더링되므로, 페이지를 렌더링하는 데 필요한 코드는 클라이언트 번들에 포함되지 않습니다.
앱이 더 크고 복잡해짐에 따라, 라우팅에 더 많은 유연성이 필요할 수 있습니다. 이러한 이유로, Nuxt는 다양한 방식으로 커스터마이징할 수 있도록 라우터, 라우트 및 라우터 옵션을 직접 노출합니다.
기본적으로, 모든 페이지는 프로젝트 루트의 app/pages 디렉터리에 있어야 합니다.
그러나 Nuxt Layers를 사용하여 앱의 페이지를 그룹화할 수 있습니다:
-| some-app/
---| nuxt.config.ts
---| pages/
-----| app-page.vue
-| nuxt.config.ts
// some-app/nuxt.config.ts
export default defineNuxtConfig({
})
export default defineNuxtConfig({
extends: ['./some-app'],
})