본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section13] 184. 내비게이션 가드 소개

내비게이션 가드는 인증과 같은 기능을 추가할 때 유용하게 쓰인다.

인증하지 않은 사용자가 특정 라우트에 액세스할 수 없도록 방지하는 경우를 예로 들 수 있다.

 

하지만 일부 코드를 실행하고 싶을 때 페이지 변화를 감지하기에도 유용하며,

사용자가 양식을 수정한 걸 저장하지 않은 상태에서 실수로 페이지를 나가지 않도록 방지하는 데에도 도움이 된다.

 

내비게이션 가드의 실용적인 사용 예시를 살펴보자.

 

# 가드란?

가드의 정확한 의미는 무엇일까?

→ 페이지가 바뀔 때 Vue 라우터로 호출하는 함수와 메서드

정확히는 내비게이션 동작이 시작될 때 호출하는 함수와 메서드.

 

예를 들어, main.js 파일에 생성한 라우터인 이 메인 라우터에서, Vue앱으로 router를 전달하기 전에 router.beforeEach를 호출할 수 있다.

router.beforeEach(function(to, from, next) {});
const app = createApp(App);
app.use(router);

beforeEach는 내장된 메서드이며, 함수를 인수로서 취한다.

 

 

Vue 라우터는 우리가 한 페이지에서 다른 페이지로 이동(navigate)할 때마다 작성한 함수를 호출한다.

beforeEach의 내비게이션 동작인 이 function() {}이 호출된다.

이 함수는 라우터로부터 가져온 세 개의 인수(to, from, next)를 취한다.

이동할 페이지의 라우트 객체인 to

'이동하기 전' 페이지의 라우트 객체인 from이 있고,

우리가 내비게이션 동작을 승인하거나 취소하기 위해 호출하는 함수인 next가 있다.

 

이게 바로 내비게이션 가드에서 실행할 수 있는 작업으로 이 작업을 '가드'라고 부르는 이유이다.

원하지 않을 땐 내비게이션 동작을 취소할 수 있다.

예를 들어 인증되지 않은 사용자일땐 내비게이션을 거부할 수 있다.

어떻게 구성할까?

 

# to, from, next()

우선 to, from에서 어떤 값을 얻는지 확인하기 위해 console.log로 출력해보자. 그 다음 별다른 설정없이 next를 호출해보자.

전역에 beforeEach 훅을 등록한 전체 라우터에 있음을 확인하기 위해서 console.log로 'Global beforeEach'를 출력해보자.

router.beforeEach(function(to, from, next) {
  console.log('Global beforeEach');
  console.log(to, from);
  next();
});

 

이대로 저장하고 페이지를 새로고침한 후 Users 페이지로 갔다가 Teams페이지로 가면 콘솔에 'Global beforeEach'가 뜬다.

그리고 to와 from 라우트 객체가 있는 로그 하나가 보인다.

 

## to

to의 경로는 /teams이다. Users 페이지에서 Teams 페이지로 이동했으므로.

그 외에는 특별한게 없다. next()를 호출했기 때문.

 

## next()

- next(): next()를 호출하면 페이지 이동(navigation)을 승인한다.

  * next()에 false를 전달할 수도 있다. 그러면 페이지 이동을 취소한다. ex: next(false)

(노트: next(true)도 이동을 허용한다.)

 next(false)로 저장하면 페이지를 새로고침해도 화면에 아무것도 없다. 페이지 로딩을 실패했기 때문. next(false)로 이동을 거부했으므로.

여전히 Global beforeEach 메서드는 실행된다. 하지만 next(false)는 이동을 취소하므로 화면에는 아무것도 뜨지 않는다.

물론 모든 이동을 취소하므로 별로 도움이 되지는 않는다.

 

* next()에 전달할 수 있는 세 번째 옵션도 있다.

next()나 next(false)외에 문자열이나 위치 객체를 전달할 수도 있다.

문자열에는 이동하려는 라우트를 작성한다. 물론 상단에 등록한 라우트 중 하나여야 한다.

router.beforeEach(function(to, from, next) {
  next('/users');
});

 

혹은 라우트를 나타내는 내비게이션 객체를 전달해보자.

예를 들어 name을 입력하고 아무 매개변수를 입력해도 된다.

이렇게 모든 내비게이션 동작이 'team-members' 이름을 갖는 라우트로 이동하도록 만들 수 있다.

매개변수는 teamId: 't2'를 쓰고.

(물론 말은 안된다. 원리를 보여주기 위해 작성했을 뿐!)

router.beforeEach(function(to, from, next) {
  next({ name: 'team-members', params: { teamId: 't2' }});
});

 

하지만 무한 루프를 생성할 수 있으니 이대로 저장하고 이 페이지를 새로고침하지 마라.

이 페이지로 이동하더라도 다시 리디렉션된다.

그러므로 if문으로 to.path나 to.name이 team-members와 일치하는지 검사해야한다.

만약 이미 team-members 페이지로 이동했다면 next()를 호출하겠지만, 다른 페이지로 이동한 경우에는 team-members 페이지로 리디렉션하자.

router.beforeEach(function(to, from, next) {
 if(to.name === 'team-members') { //'View Members' 클릭 시
   next();
 } else { // 다른 화면, Users 클릭 시
  next({ name: 'team-members', params: { teamId: 't2' }});
 }
});

 

이대로 저장한 후 페이지를 새로고침하면, Teams 페이지가 아닌 어느 페이지로 이동해도 항상 /temas/t2 페이지로 간다.

Users 페이지로 이동하려고 해도 여전히 /teams/t2로 이동한다.

왜냐하면 전역적으로 적용된 beforeEach 훅 때문이다.

 

이 로직이 말이 되지는 않지만 내비게이션 가드의 원리와 그 안에서의 next메서드 역할을 이해하고 사용하는 방법을 아는게 중요하다.

 

이제 이 코드는 주석처리하고, 이동을 허용하기 위해 next()를 호출하자.

그래야 한 페이지로만 계속 리디렉션하지 않으니.

 

사용자의 인증 여부를 검사해야 할때 유용하다.

인증하지 않은 사용자가 특정 페이지에 액세스하는걸 막을 수 있다.

 

** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.