vue3 authorization 구현하기 (navigation guards)
vue에선 정형화된 Authorization문서를 찾아보기 힘들다, 상대적으로 리액트에 비해서 서브스트림 언어라 그런게 아닌가 싶다.
아무튼, 이번 포스팅에선 vue-router의 기능으로 인증되지 않은 사용자의 접근을 막는 로직에 대해 알아보았다.
Authorization
- 가고 싶은 곳으로 가도록, 혹은 원하는 정보를 얻도록 허용하는 과정
Authentication
- 자신이 누구라고 주장하는 사람을 확인하는 절차
네비게이션 가드는 특정 URL에 접근(Navigation) 하기 전에 불려지는 훅(Hook)의 일종으로, 다른 페이지로 우회 하거나 접근 자체를 취소시킬 수 있기 때문에 네비게이션 가드라고 불린다. 예를 들어, 사용자의 인증 정보가 없으면 특정 페이지에 접근하지 못하게 제한할 수 있다.
Guards 종류
가드를 적용할 수 있는 방법은 총 세가지로 나뉜다. 동작원리는 모두 같다, 다만 URL 이동을 막기 위해 사용하는 API만 조금 다르다.
- globally guards (전역)
- per-route (특정 url에만 적용)
- in-component (라우터 컴포넌트)
- 주의!
- Params 또는 쿼리를 변경하면 네비게이션 가드가 실행되지 않는다.
인자
가드 함수가 받는 인자는 다음과 같다.
- to : 이동할 url
- from : 현재 url
- ?next : to에서 지정한 url로 이동하기 위해 꼭 호출해야 하는 함수
- tmi
next // 함수의 인자에 따라서 라우팅 허용 여부가 달라집니다. next() // : 라우팅 승인 next(false) // : 라우팅 취소 next('/') // : 특정 라우트로 진입 (route.push)처럼 진입하고자 하는 경로 지정 가능.
- 이전 버젼의 vue router에선 next를 필수로 사용해야했지만, 뷰 라우터가 업데이트 되면서 옵셔널로 사용이 가능하도록 변경됐다.
- tmi
globally guards
애플리케이션 전역에서 동작하는 전역 가드
- beforeEach()
- 생성 단계에서 호출된다.
- beforeResolve()
- 구성 요소 내 모든 가드 및 비동기 경로 구성 요소가 해결된 후 해결 가드가 호출
beforeEach()
네비게이션이 트리거될 때마다 가드가 작성 순서에 따라 호출되기 전의 모든 경우에 발생한다. 전역으로 적용되는 방식으로, router.beforeEach()를 호출하고 나면 모든 라우팅이 대기 상태가 되고, 내부 로직이 적용되고 난 이후, 리다이렉트 된다.
const router = createRouter({
routes,
});
router.beforeEach(function(to, from)) {
// ...
});
per-route
- 특정 URL에서만 동작하는 라우터 가드
beforeEnter
특정 routes객체에 접근시, 적용시켜줄 수 있다. 각 path와 component가 묶인 객체에 beforeEnter라는 key와 함수를 만들어주면, 해당 path에 연결된 componenet를 보여주기 이전에, guard로직을 적용시켜줄 수 있다.
가드는 경로가 바뀔때만 적용이된다, params, query가 바뀔때는 적용되지 않는다.
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]
in-component
- 라우터 컴포넌트 안에 정의하는 컴포넌트 가드
컴포넌트 가드는 컴포넌트 인스턴스를 통해 라우팅을 제어하는 네비게이션 가드. 목적에 따라 다시 세 종류로 나뉘지만 인자들은 앞에서 살펴본 전역, 지역 가드와 동일하다.
총 세가지 api를 통해 컴포넌트 가드를 적용할 수 있다.
- beforeRouteEnter
- 컴포넌트 인스턴스가 생성되기 전에 호출된다. 인스턴스 생성 전이기 때문에 this 를 통한 인스턴스 접근은 불가능
- beforeRouteUpdate
- 동일한 컴포넌트를 사용하지만 페이지 주소가 바뀔 경우 호출된다. 동적 라우팅을 통해서 페이지의 주소만 바뀌고 같은 컴포넌트를 재활용하는 경우에 사용
- beforeRouteLeave
- 해당 컴포넌트를 벗어나 새로운 페이지로 이동할 때 호출된다. 보통 사용자가 변경사항을 저장하지 않고 갑작스럽게 사이트를 벗어날 경우 사용된다. next(false)로 페이지 이동을 막을 수 있다.
Navigation Guard Flow
가드가 실행될 때, 흘러가는 플로우는 다음과 같다.
- 네비게이션 활성화
- 비활성화된 컴포넌트에서 beforeRouteLeave 호출
- 전역 가드 beforeEach 호출
- 재사용 컴포넌트라면 beforeRouteUpdate 호출
- routes 속성에 정의된 beforeEnter 호출
- 활성화된 컴포넌트에서 beforeRouteEnter 호출
- beforeResolve 전역 가드 호출
- 네비게이션 승인, 확인
- afterEach 전역가드 호출
- DOM 업데이트…
- 인스턴스가 있는 beforeRouteEnter 가드에서 다음으로 전달되는 콜백을 호출
다음은 실제로 가드를 적용한 예제다.
간단한 플로우차트를 그려서, 어떤 방식으로 구현할지 계획해보자.
1. 로그인을 하지 않은 상태에서, private에 접근하려하면 login 으로 리다이렉트 시켜준다.
2. 로그인을 한 이후에는, login에 접근할 수 없다.
3. 뒤로가기, url에 직접입력해도 login창에 접근할 수 없음.
전역 가드로 적용을 하고, 간단한 유저 인증을 구현했다.
그리고 유저 인증의 true, false한 값에 따라 private, login에 접근할 수 있는 방식이다.