Vue 애플리케이션에서 Vue Router 사용하는 방법
Vue Router를 사용하려면 우선 명시적으로 Vue Router를 Vue에 추가해줘야 합니다.
[Vue의 use매소드를 사용하여 Vue Router을 추가한 모습 index.js] import Vue from 'vue' import Router from 'vue-router'
Vue.use(Router) |
Vue CLI를 사용하여 프로젝트를 생성할 때 Vue Router를 사용하겠다고 선택하면 자동으로 작성되는 코드이기도 하다. 그 후 Vue Router인스턴스를 생성하고 애플리케이션에서 사용할 라우트 설정들을 Vue Router에 추가해야 한다.
[Vue Router 인스턴스를 생성하며 간단한 라우트 설정들을 추가한 모습 index.js] export default new Router({ routes: [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] }) |
route 옵션은 여러개의 라우트 설정을 가지고 있는 배열(Array)이다. 애플리케이션의 규모가 커지게 된다면 라우트의 개수도 늘어나게 되므로 라우트 설정만을 선언하는 파일을 따로 분리해줄 수도 있다.
[인증 페이지에 대한 라우트 설정과 사용자 페이지에 대한 라우트 설정 분리] // src/router/auth.js import Login from '@/components/login'
// src/router/user.js import Profile from '@/components/Profile' |
[각각 선언된 라우트 설정을 라우터에 주입하는 코드] import { AuthRouters } from '@/router/auth'
export default new Router({ routes: [ ...., AuthRouters, UserRouters ] }) |
이렇게 라우트 설정을 분리하게 될 경우 /login과 같은 경로보다는 /auth/login과 같이 모듈 이름을 경로 앞쪽에 붙여주는 것이 좋다. Vue Router가 라우트 설정 배열을 탐색할 때 배열의 머리부터 꼬리로 탐색함으로써 자연스럽게 원소간의 우선순위가 발생하기 때문에 개발자가 의도치 않은 라우트가 선택되는 것을 방지하기 위해서이다. [우선순위]
동적 라우트 매칭
- 동적 세그먼트란 무엇인가?
동적 라우트란 post/{게시글의 아이디}와 같이 경로에 변수를 가지고 있는 라우트를 의미한다. 이때 경로 내부에 들어있는 변수를 동적 세그먼트라고 한다. 동적 라우트는 같은 페이지 디자인을 가지고 있지만 다른 내용을 가질 수 있는 게시글 상세 페이지나 사용자의 정보 페이지와 같은 페이지에서 사용될 수 있다.
[동적 라우터를 선언한 모습] new Router({ routes: [ { // 동적 세그먼트는 클론으로 시작한다. { path: '/post/:postId', component: PostDetailPage } } ] }) |
이렇게 선언된 라우트의 동적 세그먼트는 컴포넌트 내에서 this.$route.params를 통해 접근할 수 있다.
[컴포넌트 내에서 ] <template> created() { console.log(`${this.$route.params.postId}번 게시글의 페이지가 로드되었습니다.`) } |
라우트는 여러 개의 세그먼트를 가질 수도 있습니다.
// 여러 개의 동적 세그먼트를 가진 라우트 { path: '/users/:userId/post/:postId', name: 'UserPost' } |
- 동적 세그먼트의 변경에 반응하기
만약 사용자가 /post/1의 경로를 가진 1번 페이지를 보고 있다가 /post/2의 경로를 가진 2번 페이지로 이동할 때 /posts/:postId와 같은 동적 라우트를 사용했다면 postId에 해당하는 동적 세그먼트가 변경되더라도 Vue Router는 이를 동일한 경로로 인식하기 때문에 한 번 사용되었던 컴포넌트를 새로 불러오지 않고 기존에 불러왔던 컴포넌트를 재사용한다. 페이지 이동 시 페이지의 모든 내용을 변경하지 않고 필요한 부분만 변경할 수 있는 클라이언트 사이드 렌더링(Client Side Rendering)의 장점을 활용하는 것이다.
이때 모든 컴포넌트를 처음부터 다시 로딩하는 것이 아니기 때문에 created나 mouted와 같은 기존에 불러왔떤 컴포넌트의 라이프 사이클 훅이 호출되지 않는다는 것을 의미한다. 그렇기 때문에 다른 방법으로 경로가 변경되었음을 감지할 수 있어야 한다. 이렇게 동일한 경로의 동적 세그먼트만 변경되는 상황에서 우리는 Vue의 watch 속성ㅇ르 사용하여 $route 객체를 감시함으로써 세그먼트가 변경되었다는 것을 감지할 수 있다.
[watch 속성을 사용하여 라우트 객체의 변경을 감지하는 모습] exrpot default { name: 'PostDetailPage', watch: { '$route' (to, from) { console.log('라우트 객체가 변경되었습니다.') } } } |
또는 Vue Router에서 제공해주는 내비게이션 가드의 일종인 beforeRouteUpdate가드를 사용하여 라우트 객체가 갱신되었음을 감지할 수도 있다.
[beforeRouteUpdate 가드를 사용하여 라우트 객체의 변경을 감지하는 모습] exrpot default { name: 'PostDetailPage', beforeRouteUpdate (to, from, next) { console.log('라우트 객체가 변경되었습니다.') // next 함수를 호출하지 않으면 다음 라우트로 이동하지 않는다. next() } } |
- 매칭 우선순위
Vue Router는 경로가 벼경되었을 때 현재 경로와 일치하는 라우트를 찾기 위해 routes 배열을 탐색한다. 이 탐색은 머리(Head)인 0번 원소부터 배열을 꼬리(Tail)인 가장 마지막 원소의 순서대로 진행된다. 이 탐색 우선순위가 왜 중요한지 알아보기 위해 두 개의 라우트를 선언해 보겠다.
[선언된 두 개의 라우트] new VueRouter({ routes: [ { path: '/posts/:postId', name: 'PostDetailPage' }, { path: '/posts/hello', name: 'HelloPost' } ] }) |
위와 같이 선언한 사용자가 /posts/hello라는 경로로 이동하면 HelloPosts 라우트가 아닌 PostDetailPage 라우트로 이동하게 된다. 그리고 라우트 객체의 게시물 아이디인 $route.params.postId는 hello라는 문자열이 될 것이다. 왜 이런 상황이 발생하는 것일까? 사용자가 /posts/hello라는 경로로 이동했을 때 VueRouter는 배열의 머리부터 탐색을 시작했기 때문에 PostDetailPage 라우트를 먼저 찾았을 것이다. 그리고 /posts/hello라는 경로는 /posts/:postId의 패턴에도 일치하는 경로이기 때문에 Vue Router는 현재 경로가 PostDetailPage 라우트의 경로인 것으로 인식한 것이다. 이런 상황을 방지하기 위해서 우리는 라우트의 우선순위를 변경해줄 필요가 있다.
[우선순위가 변경된 라우트들의 모습] new VueRouter({ routes: [ { path: '/posts/hello', name: 'HelloPost' }, { path: '/posts/:postId', name: 'PostDetailPage' } ] })
|
라우트들 간의 우선순위 때문에 발생하는 문제는 애플리케이션의 규모가 커지고 라우트가 늘어나게 되면서 생각보다 놓치기 쉽고 에러 메시지도 발생하지 않아 문제의 원인을 찾기 어렵기 때문에 라우트를 선언하는 단계에서부터 유의해서 선언하는 것이 좋다.
중첩된 라우트
- 중첩된 라우트란 무엇인가?
중첩된 라우트란 /posts/foo, /posts/bar와 같이 여러 단계로 중첩된 라우트를 말한다. 이때 /posts/foo의 경로를 사용하는 페이지와 /posts/bar의 경로를 사용하는 페이지가 레이아웃과 내용이 모두 완벽하게 다른 페이지라면 중첩된 라우트 기능은 사용할 수 없다. 그러나 이런 경로를 가지고 있는 페이지들의 경우 같은 레이아웃을 공유하되 내용이 다른 경우가 일반적이기 때문에 Vue Router는 이런 관계의 페이지들을 쉽게 정의할 수 있는 기능을 제공한다.
- 중첩된 라우트 사용하기
router-view 컴포넌트를 사용해야한다.
처음 Vue CLI를 사용하여 프로젝트를 생성하면 router-view 컴포넌트는 루트 컴포넌트인 APP.vue에만 존재한다.
[Post 컴포넌트에 router-view 컴포넌트를 삽입] <template> <router-view></router-view> |
[실제 모습은 아니지만 중첩된 라우트를 사용한 DOM 구조의 모습] <div id="app"> <router-view></router-view> <!-- 첫 번째 router-view에는 Post 컴포넌트가 렌더된다. --> <template> <!-- 중첩된 router-view에 다른 컴포넌트를 렌더할 수 있다. --> <router-view></router-view> </div> |
참고
커피 한 잔 마시며 끝내는 Vue.js
https://router.vuejs.org/kr/guide/
'vue.js' 카테고리의 다른 글
[Vue.JS] 라이프 사이클 (0) | 2020.03.09 |
---|---|
범위 컴파일 사용하기 ( slot ) (0) | 2020.02.04 |
Vue 인스턴스의 속성과 메소드 ($attrs, $set, $delete, $nextTick, $emit, $forceUpdate...) (0) | 2020.02.04 |
Vue CLI (0) | 2020.02.04 |
댓글