Skip to content

탐색 결과 기다리기

router-link를 사용할 때, Vue Router는 router.push를 호출하여 탐색을 트리거합니다. 대부분의 링크에서 예상되는 동작은 사용자를 새 페이지로 이동하는 것이지만, 사용자가 동일한 페이지에 남아 있는 몇 가지 상황이 있습니다.

  • 사용자가 탐색하려는 페이지에 이미 있음.
  • 내비게이션 가드return false로 탐색을 중단함.
  • 이전 탐색이 완료되지 않은 상태에서 새로운 탐색 가드가 실행됨.
  • 내비게이션 가드가 새 위치를 반환하여 다른 곳으로 리디렉션(예: return '/login').
  • 네비게이션 가드Error를 던짐.

탐색이 끝난 후 무언가를 하고 싶다면, router.push를 호출한 후 기다릴 방법이 필요합니다. 다른 페이지로 이동할 수 있는 모바일 메뉴가 있고, 새 페이지로 이동한 후에만 메뉴를 숨기고 싶을 때, 다음과 같이 구현했다고 가정해봅시다:

js
router.push('/my-profile')
this.isMenuOpen = false

하지만 탐색이 비동기식이기 때문에 메뉴는 즉시 닫힙니다. router.push가 반환하는 Promise를 await해야 합니다:

js
await router.push('/my-profile')
this.isMenuOpen = false

이제 메뉴는 탐색이 완료되면 닫히지만 탐색이 금지된 경우에도 닫힙니다. 현재 있는 페이지를 실제로 변경했는지 여부를 감지할 방법이 필요합니다.

탐색 실패 감지하기

탐색이 금지되어 사용자가 같은 페이지에 머무르는 경우, router.push가 반환하는 Promise의 해결된 값은 NavigationFailure입니다. 반면, 탐색이 금지되지 않은 경우에는 falsy 값이 반환됩니다(일반적으로 undefined). 따라서 이를 통해 현재 위치에서 다른 곳으로 이동했는지 구분할 수 있습니다:

js
const navigationResult = await router.push('/my-profile')

if (navigationResult) {
  // 탐색이 금지된 경우
} else {
  // 탐색이 성공한 경우 (리디렉션의 경우가 포함됨)
  this.isMenuOpen = false
}

NavigationFailure는 탐색이 차단된 이유와 이유를 알 수 있는 충분한 정보를 제공하는 몇 가지 추가 속성이 있는 Error 인스턴스입니다. 탐색 결과의 종류를 확인하려면 isNavigationFailure 함수를 사용해야 합니다:

js
import { NavigationFailureType, isNavigationFailure } from 'vue-router'

// 가정: 저장하지 않고 문서 편집 페이지에서 나가려는 경우
const failure = await router.push('/articles/2')

if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
  // 알림 표시 커스텀 함수
  showToast('저장하지 않은 변경사항이 있습니다. 삭제하고 나가시겠습니까?')
}

TIP

두 번째 파라미터를 생략하면, isNavigationFailure(failure)failureNavigationFailure인지 여부만 확인합니다.

router.afterEach() 네비게이션 가드를 사용하여 전역 탐색 실패를 감지할 수 있습니다:

ts
router.afterEach((to, from, failure) => {
  if (failure) {
    sendToAnalytics(to, from, failure)
  }
})

탐색 실패 구별하기

서두에 언급했듯이 탐색이 중단되는 여러 상황이 있으며, NavigationFailure를 반환합니다. 이것은 isNavigationFailureNavigationFailureType을 사용하여 구분할 수 있으며, 세 가지 타입이 있습니다:

  • aborted: 네비게이션 가드 내부에서 false가 반환됨.
  • cancelled: 현재 탐색이 완료되기 전에 새 탐색이 진행됨. 예를 들어 네비게이션 가드 내부에서 기다리는 동안 router.push가 호출됨.
  • duplicated: 이미 해당 위치에 있기 때문에 탐색이 차단됨.

모든 탐색 실패는 tofrom 속성을 노출하여, 현재 위치와 실패한 탐색의 대상 위치를 제공합니다:

js
// 가정: 관리자 페이지에 접근하려는 경우
router.push('/admin').then(failure => {
  if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
    failure.to.path // '/admin'
    failure.from.path // '/'
  }
})

tofrom은 항상 정규화된 라우트 위치입니다.

리디렉션 감지

네비게이션 가드 내부에서 새로운 위치를 반환할 때, 진행 중인 탐색을 재정의하는 새로운 탐색을 트리거합니다. 리디렉션은 탐색을 중지하지 않으며 새로운 값을 생성합니다. 따라서 리디렉션 여부는 라우트 위치에서 redirectedFrom 속성에 접근하는 방식으로 확인해야 합니다:

js
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
  // redirectedFrom은 네비게이션 가드에서 `to`와 `from`처럼 라우트 위치는 나타냄.
}

Translated by router.vuejs.kr