[JS]바닐라 JS로 라우팅 구현해보기

Mincho·2023년 6월 9일
0

JS

목록 보기
7/8

🔴 별도 라이브러리 없이 router기능 구현

 프로그래머스 데브 매칭에 참여하기 위해 바닐라 js만으로 코딩연습을 하고 있다. 별도의 라이브러리 없이 해야하기 때문에 개발위해 당연시 세팅했던 라이브러리 없이 코딩을 하니 좀 어려웠던 부분이 많았다. 그 중 라우팅 기능을 구현하는 것이 어려웠다. React사용시 react-router-dom을 사용해서 간단히 라우팅 처리를 하여 SPA앱을 구현했는데, 바닐라에서 어떻게 구현했는지 알아보겠다.



🟠 기본 세팅

<!DOCTYPE html>
<html lang="ko">
  <link rel="stylesheet" href="./style.css" />

  <head>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div class="app"></div>
  </body>
  <script type="module" src="./src/index.js"></script>
</html>

 html파일은 위와 같이 간단히 설정했다.

//index.js
import App from "./App.js";

new App({ $target: document.querySelector(".app") });

  index.js에 App을 렌더링하는 함수를 설정해 놓았다. 기존의 React앱에서의 동작원리와 비슷하다고 볼 수 있다.



🟡 app.js에서 통제하기

 기본적인 폴더구조는 다음과 같다

 app.js를 확인해보자

import Header from "./component/Header.js";
import MainPage from "./page/MainPage.js";
import SignupPage from "./page/SignupPage.js";
import { init } from "./route/router.js";

export default function App({ $target }) {
  this.route = () => {
    const { pathname } = location;

    /**html template을 빈 것을 초기화해주기*/
    $target.innerHTML = "";

    /**header추가하기*/
    new Header({ $target }).render();

    if (pathname === "/%EC%82%AC%EC%9B%90%20SPA/index.html") {
      new MainPage({ $target }).render();
    } else if (pathname === "/%EC%82%AC%EC%9B%90%20SPA/index.html/signup") {
      new SignupPage({ $target }).render();
    }
  };

  init(this.route);

  this.route();
}

 기본적인 뼈대 구조를 보면 쉽게 이해할 수 있을 것이다. location.pathname을 이용해 URL에 따라 경로를 다르게 설정해주는 것이다. pathname의 조건에 따라 page 렌더링을 해주는 것이다. 밑에 있는 init()함수는 밑에서 알아보자.



🔵 header에서 버튼을 클릭했을 때 라우팅해주기

import { routeChange } from "../route/router.js";

export default function Header({ $target }) {
  const $header = document.createElement("header");

  $target.appendChild($header);

  this.render = () => {
    const template = `<div id="home">Home</div>
        <div id="signup" >Signup</div>`;

    $header.innerHTML = template;
  };

  $header.addEventListener("click", ({ target }) => {
    const type = target.id;
    if (type === "home") {
      routeChange("/%EC%82%AC%EC%9B%90%20SPA/index.html");
    } else if (type === "signup") {
      routeChange("/%EC%82%AC%EC%9B%90%20SPA/index.html/signup");
    }
  });
}

여기서부터 init()함수와 routeChange() 함수를 알아보겠다.

const ROUTE_CHANGE_EVENT = "ROUTE_CHANGE";

// 커스텀 이벤트를 통해 ROUTE_CHANGE 이벤트 발생 시 onRouteChange 콜백 함수를 호출하도록 이벤트를 바인딩.
export const init = (onRouteChange) => {
  window.addEventListener(ROUTE_CHANGE_EVENT, () => {
    onRouteChange();
  });
};

// URL을 업데이트하고 커스텀 이벤트를 발생시키는 함수
export const routeChange = (url, params) => {
  history.pushState(null, null, url);
  window.dispatchEvent(new CustomEvent(ROUTE_CHANGE_EVENT, params));
};

 routeChange에 이동하고자 하는 url을 넣으면 history.pushState()에 전달되고 customEvent를 만들어 window 전달한다.

🖥️ history.pushState()
history.pushState(state, title, url) 기본 문법은 이와 같다.
State : 브라우저 이동 시 넘겨줄 데이터 (popstate 에서 받아서 원하는 처리를 해줄 수 있음)
Title : 변경할 브라우저 제목 (변경 원치 않으면 null)
Url : 변경할 주소

그리고 init을 실행하면 이것이 실행된다. 그래서 아까 app.js를 확인해보면

//app.js
export default function App({$target}){
	this.rooute = () =>{
    ////
    }
    
    init(this.route)
  
  this.route();

}

 init함수에 this.route를 전달하여 url이 변경될 때마다 this.route()를 실행하여 렌더링이 되어 SPA앱처럼 동작하는 것을 확인 할 수 있다.

참고자료
https://prgms.tistory.com/113

👍올바른 피드백은 언제든지 환영입니다~!

profile
사진찍는 개발자.

0개의 댓글