본문 바로가기

Languages/Vue

[Vue] Vue Router

728x90
반응형

0. Vue Router

 Vue Router란 Vue에서 라우팅 기능을 구현하도록 지원하는 공식 라이브러리이다. Vue Router는 Vue로 만든 페이지 간의 이동, 즉 라우팅을 가능하게 해준다. 

 

Vue Router의 공식 문서를 기반으로 Vue Router의 사용 방법을 정리해본다. 개인적으로 필요한 기능만 정리했기에 추가적으로 필요한 기능들은 Vue Router의 공식 문서를 확인하는 것을 권장한다.

 

추가로 여기서 정리하는 Vue Router는 3.x 버전이다. Vue Router 3.x가 Vue 2와 호환되기 때문에 Vue Router 3.x를 정리한다.

 

1. 동적 라우트 매칭

동일한 컴포넌트를 사용하지만 내용이 서로 다른 경우에 사용하다. 

 

모든 사용자에 대해 동일한 UI를 제공하지만 사용자마다 실제 보여지는 정보는 id에 따라 다르다. -> 동적으로 바뀌는 id

const User = {
  template: '<div>User</div>'
}

const router = new VueRouter({
  routes: [
    // 동적 세그먼트는 콜론으로 시작합니다.
    { path: '/user/:id', component: User }
  ]
})

 

단 동적 라우트 매칭을 사용할 때 주의할 점이 있다. 만약 같은 주소에서 id만 바꾼채 이동할 경우, 즉 params나 query만 변경되는 경우 컴포넌트는 변경되지 않는다. 이로인해 컴포넌트의 라이프 사이클 훅이 호출되지 않는다. 라이프 사이클 훅이 호출되지 않으면 개발자가 원하는 방향대로 반응하지 않을 가능성이 매우 크다. 

 

이 경우 두가지 해결방법이 있다.

 

1. $router에 직접 watch를 건다.

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 경로 변경에 반응하여...
    }
  }
}

2. beforeRouteUpdate를 사용한다.

const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

 

여기서 beforeRouteUpdate는 네비게이션 가드에 관한 내용으로 네비게이션 가드에서 더 자세히 설명한다.

 

 

2. 중첩된 라우트

여러 단계로 중첩된 컴포넌트에 대해서 URL도 중첩되게 구성하는 것은 매우 일반적이다. Vue Route는 이에 대해 솔루션을 제공한다.

 

router의 옵션을 설정할 때 children을 통해 하위 url을 설정할 수 있다. 

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
          // /user/:id/profile 과 일치 할 때
          // UserProfile은 User의 <router-view> 내에 렌더링 됩니다.
          path: 'profile',
          component: UserProfile
        },
        {
          // /user/:id/posts 과 일치 할 때
          // UserPosts가 User의 <router-view> 내에 렌더링 됩니다.
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

 

또한 빈 서브 라우트에도 할당 가능하다.

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id', component: User,
      children: [
        // UserHome은 /user/:id 가 일치 할 때
        // User의 <router-view> 안에 렌더링됩니다.
        { path: '', component: UserHome },

        // ...또 다른 서브 라우트
      ]
    }
  ]
})

 

 

3. 선언적 방식과 프로그래밍 방식

네비게이션을 수행할 때는 선언적 방식과 프로그래밍 방식이 있다. 

 

  • 선언적 방식 : <router-link :to="..."> : template에서 사용
  • 프로그래밍 방식 : this.$router.push(...) : script에서 사용

 

4. router-view

router-view란 매칭되는 컴포넌트가 렌더링되는 곳이다. router-link에 의해서 매칭된 컴포넌트는 router-view에서 렌더링된다. 즉 라우팅에 의해 렌더링되는 컴포넌트의 위치를 지정한다. 

 

라우팅에 의해 렌더링되는 부분과 그렇지 않은 부분을 분리함으로써 네비바와 같이 고정적인 컴포넌트가 존재할 때 유용하게 사용할 수 있다.

 

Named View

한 화면에서 여러 개의 router-view가 존재할 수 있다. 이 때는 각각의 router-view를 구분하기 위해 router-view마다 이름을 붙인다.

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

 

 

5. 라우트 컴포넌트에 props 전달

router-view는 router-link에 매칭되는 하나의 컴포넌트이며 따라서 props를 전달할 수 있다. 이에 대해 Vue Router는 router에 props를 전달할 수 있는 세가지 솔루션을 제공한다.

 

Boolean Mode 

router 옵션을 설정할 때 props를 true로 놓으면 route.param이 props로 설정된다.

 

Object Mode 

props를 객체로 놓으면 그 자체가 props로 설정된다.

const router = new VueRouter({
  routes: [
    { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
  ]
})

 

Function Mode

props를 반환하는 함수를 만든다. 이를 통해 props를 동적으로 생성할 수 있다.

const router = new VueRouter({
  routes: [
    { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
  ]
})

 

 

6. 리다이렉트

"A에서 B로 리다이렉트 한다."는 "사용자가 A에 접근하면 B로 매칭한다."라는 뜻이다.  리다이렉트 기능은 다양하게 사용 가능하다. 예를 들어 로그인을 하지 않은 사용자가 로그인이 필요한 페이지(A)에 접근할 경우 로그인 페이지(B)로 이동시킬 수 있다.

 

경로나 이름에 직접 매칭시킬 수 있다.

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})


const router = new VueRouter({
  routes: [
    { path: '/a', redirect: { name: 'foo' }}
  ]
})

 

또한 함수를 통해 동적으로 매칭시킬 수도 있다.

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 함수는 인수로 대상 라우트를 받습니다.
      // 여기서 path/location 반환합니다.
    }}
  ]
})

 

 

7. 네비게이션 가드

네비게이션 가드는 이름에서도 알 수 있듯이 라우터의 이동을 막거나 리다이렉팅을 하는 기능이다. 

 

적용 범위에 따라 전역 가드, 라우트 별 가드, 컴포넌트 내부 가드로 나뉜다. 

 

가드의 호출 타이밍에 따라 before가드와 after 훅으로 나뉜다.

 

전역 가드

beforeEach

  • 이동할 라우트의 컴포넌트들을 불러오기 전에 실행되는 훅이다.
  • 애플리케이션 내부에서 네비게이팅이 수행될 때마다 호출되는 전역가드이다.
  • 주로 전역에서 공통적으로 수행해야 하는 동작을 정의할 때 사용한다.
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

 

afterEach

  • 네비게이션 작업이 완료된 후 호출된다.
  • 따라서 네비게이션 작업에 영향을 미치지 않는다.
router.afterEach((to, from) => {
  // ...
})

 

라우트 별 가드

beforeEnter

  • 이동하려는 라우트에 진입 전 호출된다.
  • 라우트마다 다르게 지정할 수 있다.
  • 라우트 설정에서 직접 정의할 수 있다.
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

 

컴포넌트 내부 가드

beforeRouteEnter

  • 새로운 컴포넌트를 만들기 전 호출된다.
  • 컴포넌트가 생성되기 전이기 때문에 this를 통해 컴포넌트에 접근할 수 없다.
  • 대신 next를 통해 접근 가능하다.

beforeRouteLeave

  • 컴포넌트가 제거되기 전에 호출된다.
  • 아직 컴포넌트가 존재하므로 this를 통해 접근이 가능하다.
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 이 컴포넌트를 렌더링하는 라우트 앞에 호출됩니다.
    // 이 가드가 호출 될 때 아직 생성되지 않았기 때문에
    // `this` 컴포넌트 인스턴스에 접근 할 수 없습니다!
  },
  beforeRouteLeave (to, from, next) {
    // 이 컴포넌트를 렌더링하는 라우트가 이전으로 네비게이션 될 때 호출됩니다.
    // `this` 컴포넌트 인스턴스에 접근 할 수 있습니다.
  }
}

 

 

8. Data Fetch

라우팅 과정에서 서버로부터 Data Fetch가 필요한 상황이 존재한다.

 

Data Fetch를 하는 방법에는 두 가지가 있으며, 상황에 따라 유연하게 사용하면 된다.

 

Fetching Before Navigation

beforeRouteEnter에서 Data Fetch를 한 후 next를 통해 호출한다. fetch하는 동안 사용자는 원래 페이지에 머무르게 된다.

 

Fetching After Navigation

created에서 Data Fetch를 한다. fetch되는 동안 사용자는 이동할 페이지에서 기다린다.

 

두 가지 방법 전부 사용자가 대기하는 시간이 존재하므로 Data Fetch하는 시간이 오래 걸린다면 로딩 표시와 같은 효과를 주는 것이 좋다.

728x90
반응형

'Languages > Vue' 카테고리의 다른 글

[Vue] Vue2 & Vue3 차이점  (0) 2022.06.20