내비게이션 결과 기다리기
router-link를 사용할 때 Vue Router는 내비게이션을 트리거하기 위해 router.push를 호출합니다. 대부분의 링크는 사용자를 새 페이지로 이동시키는 것이 기대되는 동작이지만, 사용자가 같은 페이지에 머무르게 되는 몇 가지 상황이 있습니다:
- 사용자가 이미 이동하려는 페이지에 있는 경우
- 내비게이션 가드가
return false를 실행해 내비게이션을 중단하는 경우 - 이전 내비게이션이 끝나기 전에 새 내비게이션이 시작되는 경우
- 내비게이션 가드가 새 location을 반환해 다른 곳으로 리다이렉트하는 경우(예:
return '/login') - 내비게이션 가드가
Error를 throw하는 경우
내비게이션이 끝난 뒤 무언가를 하고 싶다면 router.push 호출 뒤에 기다릴 방법이 필요합니다. 예를 들어 여러 페이지로 이동할 수 있는 모바일 메뉴가 있고, 새 페이지로 이동한 뒤에만 메뉴를 숨기고 싶다면 다음과 같이 하고 싶을 수 있습니다:
router.push('/my-profile')
this.isMenuOpen = false하지만 이렇게 하면 내비게이션이 비동기 이기 때문에 메뉴가 즉시 닫혀 버립니다. 따라서 router.push가 반환한 Promise를 await해야 합니다:
await router.push('/my-profile')
this.isMenuOpen = false이제 내비게이션이 끝나면 메뉴가 닫히지만, 내비게이션이 막혔을 때도 닫히게 됩니다. 실제로 페이지가 바뀌었는지 여부를 감지할 방법이 필요합니다.
내비게이션 실패 감지하기
내비게이션이 막혀 사용자가 같은 페이지에 머무르게 되면, router.push가 반환한 Promise의 resolve 값은 Navigation Failure 가 됩니다. 그렇지 않으면 falsy 값(보통 undefined)이 됩니다. 이를 통해 실제로 현재 위치에서 다른 페이지로 이동했는지 아닌지를 구분할 수 있습니다:
const navigationResult = await router.push('/my-profile')
if (navigationResult) {
// 내비게이션이 방지됨
} else {
// 내비게이션 성공(리다이렉트된 경우도 포함)
this.isMenuOpen = false
}Navigation Failure 는 어떤 내비게이션이 왜 막혔는지 알 수 있도록 몇 가지 추가 속성을 가진 Error 인스턴스입니다. 내비게이션 결과의 성격을 확인하려면 isNavigationFailure 함수를 사용하세요:
import { NavigationFailureType, isNavigationFailure } from 'vue-router'
// 저장하지 않은 채 기사 편집 페이지를 떠나려는 경우
const failure = await router.push('/articles/2')
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
// 사용자에게 작은 알림을 표시합니다
showToast('You have unsaved changes, discard and leave anyway?')
}TIP
두 번째 매개변수(isNavigationFailure(failure))를 생략하면, failure가 Navigation Failure 인지만 확인합니다.
전역 내비게이션 실패
router.afterEach() 내비게이션 가드를 사용하면 전역 내비게이션 실패를 전역적으로 감지할 수 있습니다:
router.afterEach((to, from, failure) => {
if (failure) {
sendToAnalytics(to, from, failure)
}
})내비게이션 실패 구분하기
처음에 말했듯이 내비게이션을 중단시키는 상황은 여러 가지이며, 각각 서로 다른 Navigation Failure 로 이어집니다. 이들은 isNavigationFailure와 NavigationFailureType을 사용해 구분할 수 있습니다. 유형은 세 가지입니다:
aborted: 내비게이션 가드 안에서false가 반환되어 내비게이션이 중단됨cancelled: 현재 내비게이션이 끝나기 전에 새 내비게이션이 발생함. 예: 내비게이션 가드 안에서 기다리는 동안router.push가 호출됨duplicated: 이미 대상 location에 있기 때문에 내비게이션이 방지됨
Navigation Failure 의 속성
모든 내비게이션 실패는 현재 location과 실패한 내비게이션의 대상 location을 나타내는 to와 from 속성을 노출합니다:
// 관리자 페이지에 접근하려는 경우
router.push('/admin').then(failure => {
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
failure.to.path // '/admin'
failure.from.path // '/'
}
})모든 경우에 to와 from은 정규화된 라우트 location입니다.
리다이렉트 감지하기
내비게이션 가드 안에서 새 location을 반환하면, 진행 중인 내비게이션을 덮어쓰는 새 내비게이션이 트리거됩니다. 다른 반환값과 달리 리다이렉트는 내비게이션을 막는 것이 아니라 새로운 내비게이션을 생성합니다. 따라서 확인 방식도 다르며, Route Location의 redirectedFrom 속성을 읽어 확인합니다:
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
// redirectedFrom은 내비게이션 가드의 to와 from처럼 resolve된 라우트 location입니다
}