네트워크에서 라우터는 네트워크와 둘 이상의 네트워크 사이의 연결을 말해준다. 하지만, 코딩에서의 라우터는 네트워크의 의미와 비슷하면서도 다르다.
SPA(Single Page Application)를 구현하기 위해 사용하게 되는 방식이다. SPA는 한 페이지만을 이용하여 여러 페이지를 보여주는 방식으로,
이때 한 페이지에 여러 페이지의 내용을 렌더링 해주는 것이 "라우터(Router)"이다.
위의 그림처럼 한 페이지에서 여러 페이지를 렌더링하려면 라우터 방식을 이용해야한다.
프로젝트를 하며 SPA를 처음 접했는데, 이 부분에서 많은 어려움이 있었다.
React를 사용해 보았던 팀원들은 React에서의 라우터 구현은 어렵지는 않다고 하였지만, 바닐라 JS를 사용하여 라우터를 사용해 본 팀원은 없었기에
프로젝트 시작부터 난관이였다. 하지만, 우리에겐 아주 편리한 라이브러리가 있었다.
출처 : https://github.com/krasimir/navigo
"Navigo Router"는 JS 환경에서 쉽게 SPA를 구현하게 도와주는 라우터 라이브러리이다.
이번 프로젝트의 경험을 바탕으로 기본적인 기능 사용법을 남겨두려고 한다.
혹시나 JS 환경에서 Router를 이용하여 SPA를 구현하려면 꼭 Router 먼저 구현하여 페이지의 기본 틀을 잡고 시작하자.
이유는 나도 알고싶지 않았다..
개발을 시작하기 전에 어떤 라이브러리를 쓸 것인지 어떤 번들러를 사용할 것인지, 미리 생각하고 셋팅하고 시작하자.
가장 먼저 로컬 스토리지 또는 우리의 프로젝트 내에 Navigo를 설치하자.
방법은 두 가지가 있다.
// html 페이지 내에 작성하여 사용하는 방법
<script src="//unpkg.com/navigo"></script>
// 로컬 스토리지 내에 설치하는 방법
> npm install navigo --save // npm 기준
> yarn add navigo -S // yarn 기준
SPA(Single Page Application)은 말 그대로 싱글 페이지이다.
즉 html은 index.html
하나만을 이용하자.
(bundle은 parcel을 이용했다.)
그 이후에 main.js
에서 Navigo를 불러온다.
import Navigo from 'navigo'; // ES Module을 사용할 때
const router = new Navigo('/');
.on()
는 경로가 설정되어 있는 태그를 클릭했을 때 해당하는 내용을 렌더링 및 함수를 실행하는 역할을 한다.
navigo는 기본적인 경로를 확인하지 않기 때문에, router를 쓸 때 최소 한번은 .resolve()
메서드를 사용하여 경로를 확인한다.
<ul>
<li>
// about이라는 경로를 설정(about은 예시다.)
//( "/"는 꼭 붙이도록 하자. 붙이지 않으면 주소가 중복되는 현상이 생길 수 있다.)
<a href="/about">about</a>
</li>
<div id="app"></div>
</ul>
function aboutRender(){
const app = document.querySelector(#app)
app.innerHtml = "~~~"
}
router
.on({
"about" : () => {
//렌더링 할 페이지의 함수
aboutRender()
}
}).resolve()
.navigate()
는 사용자가 어떤 페이지를 렌더
나는 주로 로그인 관련한 페이지 가드(Page Guard)를 이용할 때 사용했다.
예를 들어, 회원이 아닌 사용자가 내 정보 기능 등을 이용할 때 해당 메서드를 이용하여 로그인 페이지로 이동시켰다.
if(match.url==="mypage" && !user){
// 인수로 router.on 에 작성한 키 값을 넣으면, 해당 키의 함수를 실행한다.
.navigate("login")
}
.hooks()
: 페이지가 렌더링 되기 전과 된 후를 이벤트를 조종한다.
before()
: 페이지가 렌더링 되기 전의 이벤트를 발생한다.
after()
: 페이지가 렌더링 된 후 이벤트를 발생한다.
before(done,match)
의 인수에서 done
과 match
라는 것이 있는데 이것은 필수적으로 쓰인다.
done()
은 렌더링 되기 전에 작성된 이벤트를 완료했다는 의미이다.
(즉, 검문 끝났으니 지나가도 좋다! 이런 느낌이다.)
match
는 사용자가 어떤 것을 렌더링할 것인지에 대한 주소와 그에 해당하는 정보들이 들어가있다.
(hooks 뿐만 아니라 .on()에서도 사용 가능하다.)
before()
와 after()
는 .hooks()
안에서 사용할 수 있으며,
.addBeforeHook()
과.addAftreHook()
메서드와 같다.
간단한 예시로 페이지 가드를 예시를 들어보겠다.
before() 예시
router.hooks({
before (done, match) => {
//토큰값 확인
const accessToken = JSON.parse(localStorage.getItem('accessToken'));
const auth = await authCheck(accessToken);
//오직 회원만 이용 가능한 페이지 배열
const onlyUserPages = ['mypage'];
// 페이지 가드
// match는 console.log로 찍어보면 컨트롤할 수 있다.
if (onlyUserPages.includes(match.url) && !auth) {
router.navigate('login');
done(); //로그인으로 이동하고, Before()함수는 끝!
// break와 같은 느낌
}
})
after() 예시
after: (match) => {
window.scroll(0, 0);
}, // 페이지 렌더링이 완료 된 후 스크롤이 항상 맨 위로 가도록 설정.
.notFound()
는 navigo router로 정의하지 않은 페이지를 어떻게 처리할 것인지 정의하는 메서드이다.
const router = new Navigo('/');
router.notFound(() => {
// this runs if there is no match found
errorPageRender()
});
개발을 시작한지 얼마 되지 않아서, 항상 MPA 또는 단일 페이지만 만들다가
처음으로 팀 프로젝트를 접하면서 많은 것을 얻어가는 시간이었다.
특히 SPA를 구현하는 방법과 왜 JS환경에서 라우터가 손이 많이 가는지도 알게되었고, 페이지 가드를 어떻게 구현하는지도 알게되어 도움이 되는 시간이었다. navigo라는 라이브러리 덕분에 이번 프로젝트에서 많은 도움을 받았고, 혹시나 다음에 또 쓰게 되는 날이 오거나 누군가 이것을 보고 도움이 되었음 하는 바람에 블로그를 작성했다.(리액트를 하면 이건 잘 안쓰게 되겠지 ㅎㅎ)
위의 코드만 이용해도 충분히 SPA를 구현할 수 있다. 혹시나 더 많은 것을 알고 싶거나, 자세한 정보를 보고 싶다면
https://github.com/krasimir/navigo/blob/master/DOCUMENTATION.md#direct-matching-of-registered-routes
해당 문서를 읽어보길 바란다. 끝!