SPA Framework의 Router 구현해보기 - (1)

박춘화·2022년 3월 9일
0

먼저 예제를 위해 필요한 파일들을 생성해보자.

index.html

<!DOCTYPE html>
<html>
<head>
	<title>Parcel Sandbox</title>
	<meta charset="UTF-8" />
</head>
<body>
	<div id="app"></div>
	<script src="src/index.js">
	</script>
</body>
</html>

App.js

export default function App({ $parent }) {
  this.render = () => {};
  this.render();
}

index.js

import App from "./App.js";

new App({ $parent: document.querySelector("div#app") });

페이지 만들기

페이지는 메인 페이지, 상세 페이지, 404 페이지 세개를 구현한다.

페이지는 모두 다음과 같은 형식을 갖추고 있다.

export default function Page({ $parent }) {
  const $page = document.createElement("div");

  $parent.appendChild($page);

  this.render = () => {
    $page.innerHTML = `
    <h1>페이지입니다.</h1>
    `;
  };

  this.render();
}

현재 URL에 따라 페이지 불러오기

URL에 대한 정보를 받기 위해 location Web API의 pathname 프로퍼티를 사용한다.

App.js

import MainPage from "./pages/MainPage";
import DetailPage from "./pages/DetailPage";
import NotFoundPage from "./pages/NotFoundPage";

...

this.render = () => {
  const { pathname } = location;
  
  if (pathname === '/') {
    new MainPage({ $parent });
  } else if (pathname === '/detail') {
    new DetailPage({ $parent });
  } else {
    new NotFoundPage({ $parent });
  }
};

...

이제 URL에 따라 해당하는 페이지를 불러온다. 하지만 여기에는 몇가지 문제점이 있다.

  • 현재 페이지에서 다른 페이지로 이동할 때, 애플리케이션에게 페이지의 이동을 알리는 장치가 없다. 페이지의 이동을 알리는 장치가 필요하다.
  • 페이지 이동 시 App 내부에 DOM Element가 누적된다. 페이지 이동 시에 App 내부 DOM Element를 초기화시켜줘야한다.

해당 기능을 구현하기 위해 Router를 구현해보자.

History.pushState

Router 구현에 앞서 History Web API에 대해 알 필요가 있다. MDN 문서에서 History Web API를 다음과 같이 정의하고 있다.

History 인터페이스는 브라우저의 세션 기록, 즉 현재 페이지를 불러온 탭 또는 프레임의 방문 기록을 조작할 수 있는 방법을 제공합니다.

History Web API는 다양한 메서드를 제공하는데, 그 중에서 Router 구현에 사용할 메서드는 History.pushState다.

History.pushState는 다음과 같이 3개의 매개변수를 가진다.

History.pushState(state, title[, url])

  • state: 새로운 세션 기록 항목에 사용할 상태 객체로 사용자가 이동할 때마다 popstate 이벤트가 발생하는데, 이때 이벤트 객체의 state 속성으로 사용될 객체의 원본이 된다.
  • title: 현재 대부분의 브라우저에서 사용하지 않는 매개변수로, 추후에 새로운 세션 기록 항목의 제목으로 사용될 값이다.
  • url: 새로운 세션 기록 항목의 URL로 현재 URL과 동일 출처를 가져야한다.

window.location 또한 새로운 세션 기록 항목을 생성한다는 점에서 History.pushState와 비슷하지만, History.pushState는 다음과 같은 장점을 가진다.

  • 새로운 URL은 같은 출처에 한해서 어떤 URL로도 가능하며, 동일한 문서에서 이루어진다. 그에 반해 window.location은 해시(#)가 아닌 경우 다른 문서로 이동한다.
  • URL의 변경이 이루어지지 않아도 새로운 세션 기록 항목을 생성할 수 있다. window.location은 해시가 변경된 경우에만(hashchange 이벤트 발생 시) 새로운 세션 기록 항목을 생성한다.
  • state에 직렬화 가능한 데이터라면 임의의 데이터를 세션 기록 항목에 연결할 수 있다. 그에 반해 해시 기반 방식은 모든 데이터를 인코딩해 짧은 문자열로 변환해야한다.

참고 자료

profile
함께 성장하는 개발자

0개의 댓글