한준호

prototype을 이용하여 vue router 예외처리 전역으로 하기 본문

Frontend/Vue js

prototype을 이용하여 vue router 예외처리 전역으로 하기

igoman2 2021. 9. 11. 19:51
728x90

vue router를 사용하다보면 NavigationDuplicated와 같은 에러를 핸들링 하기 위해

이와 같이 push 뒤에 catch문을 넣는 경우가 있다.

 

* NavigationDuplicated 에러는 현재 보고있는 페이지와 같은 주소로 라우팅 처리를 할때 발생하는 에러이다.

 

 

하지만 매 컴포넌트마다 같은 예외처리 코드를 넣어주는 것은 코드 중복이 발생하므로 이를 피하기 위해 전역 라우터 함수에 예외처리를 넣어줄 수 있다.

 

우선 router를 초기화 하는 js파일을 들어간다.

router.js

 

이제 상단에 아래 코드를 삽입해준다.

Vue.use(Router);
const originalPush = Router.prototype.push;						// 1
Router.prototype.push = function push(location) {					// 2
  return originalPush.call(this, location).catch((err) => {			
    if (err.name !== "NavigationDuplicated") throw err;
  });
};

 

차근차근 살펴보자면,

Vue.use(Router)는 vue 인스턴스의 Router를 사용한다는 의미이고(99%의 확률로 이미 선언해논 상태일 것이다.) 상단에 

import Router from "vue-router";

이런 식으로 Router라는 동일한 이름이 임포트 된 것을 볼 수 있을 것이다. (Router가 아니어도 마음대로 네이밍 할 수 있다.)

 

originalPush 변수는 Router가 가지고 있는 프로토타입 메서드 push를 가리킨다

Router.prototype.push(=originalPush)를 출력해보면

와 같이 나오는 것을 알 수 있는데, onCompletion과 onAbsort는 2.2.0 버전 이후로 제공되는 콜백이며 탐색이 성공적으로 완료되거나 중단될때 호출되는 인자들이다.

중요한 것은 location, 즉 라우팅되는 목적지에 대한 정보를 가지고 있는 인수다.

 

2번을 보면 prototype메서드를 커스텀 하고 있는데, originalPush의 call메서드를 사용하여 this문맥과 매개변수 location을 전달하여 originalPush라는 객체의 this에 location을 바인딩 시킨 후 catch문을 통해 예외처리를 하여 return한다.

위 코드에서 예외처리한 내용은 error의 이름이 NavigationDuplicated가 아니면 에러를 발생시키고 맞으면 아무것도 하지않는, 즉 에러를 발생시키지 않고 그냥 진행하도록 하였다.

return된 originalPush를 Router.prototype.push 메서드에 할당되고 있으므로 해당 Vue 인스턴스 내에서 this.$router.push로 사용되던 동작은 커스텀된 동작으로 대체되는 것이다.

 

즉 call 메서드를 통해 원래 push메소드를 가져와 location을 바인딩 시켜 개조한 것으로 이해하였다.

 

다시 Router.prototype.push를 출력해보면 잘 변경이 된 것을 볼 수 있다.

 

이를 통해 routing 예외처리를 전역으로 진행할 수 있으며 같은 원리로 onCompletion과 onAbort에 대한 콜백 처리도 커스텀 할 수 있다.

 

 

한가지 실험을 위해 다음과 같이 코드를 대체해보자.

const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
  return originalPush.call(this, location).catch((err) => {
    console.log(location);
    if (err.name !== "NavigationDuplicated") throw err;
    else {
      console.log("@@@@@");
    }
  });
};

이 코드대로라면 this.$router.push를 통해 같은 페이지로 또다시 라우팅을 할 때 location을 출력하고 NavigationDuplicated가 발생할 것이기 때문에 @@@@@를 출력할 것이다.

 

url
console

잘 호출된 것을 알  수 있다.

728x90
Comments