14. vue-router version 4 beforeEach, beforeResolve, beforeEnter
전역: beforeEach 가드
const router = createRouter({
// ...
})
router.beforeEach((to, from) => {
// ...
// 탐색을 취소하려면 명시적으로 false를 반환해야 함.
return false
})
탐색이 트리거될 때마다 등록 순서대로 전역 비포 가드 가 호출된다.
가드는 비동기식으로 해결될 수 있으며, 탐색은 모든 훅이 해결되기 전까지 대기 중(pending
)으로 간주한다.
모든 가드 함수는 2개의 인자를 받는다.
to
: 탐색될 경로 위치 객체from
: 탐색 전 현재 경로 위치 객체
그리고 선택적으로 다음 값 중 하나를 반환할 수 있다.
false
: 현재 탐색을 취소한다. URL이 변경된 경우,from
경로로 URL이 재설정된다.경로 위치 정보
:router.push()
를 사용할 때처럼 경로 위치(문자열 또는 객체)를 전달한다.
현재 탐색이 중단되고, 기존from
위치에서 새로운 탐색 동작이 생성된다.
router.beforeEach(async (to, from) => {
if (
// 유저 로그인 인증여부 확인
!isAuthenticated &&
// ❗ 무한 리디렉션 방지
to.name !== 'Login'
) {
// 유저를 로그인 페이지로 리디렉션
return { name: 'Login' }
}
})
예외 상황 시 Error
를 던질 수도 있다.
이 경우에도 탐색은 취소되고 router.onError()
메서드에 전달돼, 등록된 모든 콜백 함수를 호출한다.
undefined
, true
또는 아무것도 반환되지 않으면, 탐색이 유효하다고 판단하고 다음 탐색 가드가 호출된다.
위의 모든 설명은 async
함수 및 Promise
에서 동일한 방식으로 작동한다.
router.beforeEach(async (to, from) => {
// canUserAccess()는 `true` 또는 `false` 중 하나를 리턴함
const canAccess = await canUserAccess(to)
if (!canAccess) return '/login'
})
선택적 세번째 인자 next
Vue Router
의 이전 버전에서는 세번째 인자 next
를 사용할 수도 있었는데, 이는 일반적인 실수의 원인이었으며, RFC를 이유로 제거했다.
그러나 여전히 지원되므로 탐색 가드에서 세번째 인자를 전달받을 수 있다.
이 경우, 트리거되는 탐색 가드별 정확히 한 번만 next
를 호출해야 한다.
그렇지 않으면 영원히 훅이 해결되지 않거나 오류가 생긴다.
다음은 인증되지 않은 사용자를 /login
으로 리디렉션하는 나쁜 예제이다.
// BAD
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// 사용자가 인증되지 않은 경우, `next`가 두 번 호출됨
next()
})
올바른 예제:
// GOOD
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
전역: beforeResolve 가드
router.beforeResolve
로 전역 가드를 등록할 수 있다.
이것은 모든 탐색에서 트리거되기 때문에 router.beforeEach
와 유사하지만, 컴포넌트 내 가드 및 비동기 경로 컴포넌트가 모두 해결된 후, 최종적으로 탐색을 진행할 것인지 결정하기 위한 목적으로 호출한다.
다음은 사용자 정의 meta를 정의한 속성 requiresCamera
가 있는 경로에 대해,
사용자가 카메라에 접근 권한을 부여했는지 확인하는 예이다.
router.beforeResolve(async to => {
if (to.meta.requiresCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
// ... 오류를 처리한 다음 탐색을 취소합니다.
return false
} else {
// 예기치 않은 오류, 탐색을 취소하고 오류를 전역 핸들러에 전달
throw error
}
}
}
})
유저가 페이지에 접근할 수 없는 경우, router.beforeResolve
는 이것을 처리하기 위해 데이터를 가져오거나 다른 작업을 실행하기에 이상적인 곳이다.
전역: afterEach 훅
전역으로 탐색 후 훅을 등록할 수도 있지만, 가드와 달리 next
함수를 전달받지 않으며, 탐색에 영향을 줄 수 없다.
router.afterEach((to, from) => {
sendToAnalytics(to.fullPath)
})
애널리틱스, 페이지 <title>
변경, 페이지 정보를 알리는 접근성 기능 및 기타 여러 작업에 유용하다.
또한 탐색 실패를 세번째 인자로 전달한다.
router.afterEach((to, from, failure) => {
if (!failure) sendToAnalytics(to.fullPath)
})
참고: 가이드 - 탐색 실패