til

Router 만들기

fpzmfks 2024. 8. 27. 20:30

오늘은 미완성이나마 Router 만들기 과제를 마쳤다. 그리고 useSyncExternalStore 사용하기 과제를 받았다... 과연 챌린지반인지 점점 과제가 어려워져서 개인과제를 진작 마치지 않았으면 어쩔 뻔 했는지 모르겠다. 오늘은 아티클을 읽으면서 과제를 하는데, 기존에 배운 것 중에도 아티클 내에도 없는 것으로 코드를 완성해야되어서 한참을 고민을 하다가 타임아웃을 받은 참이다. 

 

어쩔 수 없는 일이니만큼 나중에 질문시간을 활용해서 답을 찾을 수 있으면 좋을 것이다.

 

다만 주요 목표인 Router 만들기 자체는 성공했기 때문에 오늘 이렇게 글을 쓸 수 있게 되었다. 

 

아래가 가장 핵심적인 함수가 담긴 객체를 반환하는 Router 함수이다.

 

fragment를 인자로 받아서 경로를 변경하는 navigate함수를 이용하여 replace방식으로 페이지를 이동할 수 있다. 

export default function createRouter() {
  const router = {
    // replace로 페이지 이동 / push로 페이지 이동
    navigate: (fragment, replace = true) => {
      if (replace) {
        // 이동할 경로 저장
        const href = window.location.href.replace(
          window.location.hash,
          "#" + fragment
        );
        // 페이지 이동
        window.location.replace(href);
      } else {
        window.location.hash = fragment;
      }
    },
  };
  return router;
}

 

아티클에서는 이 중 fragment에 인자로 넘어갈 값을 button에 data-navigate로 할당해서 사용했다. 아래는 위 함수를 실행하는 코드이다. 

<button data-navigate="/">Home</button>
<button data-navigate="/rara">Rara</button>



// 클릭 이벤트 시 페이지 이동
window.addEventListener("click", (event) => {
  // 이동할 경로 지정
  if (event.target.matches("[data-navigate")) {
    if (event.target.dataset.navigate === "/") {
      // html 그리기
      container.innerText = "";
      pages.home();
    } else if (event.target.dataset.navigate === "/rara") {
      // html 그리기
      container.innerText = "";
      pages.rara();
    }
    // 페이지 이동
    router.navigate(event.target.dataset.navigate);
  }
});

 

여기까지가 핵심적인 로직이고,


 

아래는 router가 경로를 저장하고 경로가 변경됨에 따라 알맞은 html을 그리기까지 하기 위한 함수들이다. 

export default function createRouter() {
  const routes = []; //경로
  const router = {
    // 경로 저장
    addRoute(fragment, component) {
      routes.push({ fragment, component });
      return this;
    },

    // 경로에 따라 html 그리기
    start: () => {
      const checkRoutes = () => {
        // 경로 검사
        const currentRoute = routes.find(
          (route) => route.fragment === (window.location.hash || "#/")
        );
        // html 그리기
        currentRoute.component() || [];
      };
      // 페이지 이동 시 html 그리기
      window.addEventListener("hashchange", checkRoutes);
      checkRoutes();
    },
  };
  return router;
}

 


 

그리고 경로로부터 정보를 가져와 html에 그리는 코드를 작성하였는데, 정규식의 구조나 경로를 잘라서 가져오는 과정을 이해할 수 없어서 이 부분만은 실패하고 말았다. 타임아웃을 받아서 일단 여기서 그만두기는 했지만, 언젠가 이러한 구조에서 경로를 가져오는 방법도 알 수 있게 되면 좋겠다. 

addRoute(fragment, component) {
  // 이 부분에서 name과 song을 추출해서 params에 넣는 것이 문제인데, 정규식을 채 이해하지 못했기 때문에 필요한 부분만 추출해서 저장할 수 없었다.
  const params = [];
  // 정규표현식과 replace 함수를 이용하여 name과 song 추출
  const parsedFragment = fragment
    .replace(ROUTE_PARAMETER_REGEXP, (name, song) => {
      params.push(name);
      params.push(song);
      return URL_REGEXP;
    })
    .replace(/\//g, "\\/");

  routes.push({
    fragmentRegExp: new RegExp(`^${parsedFragment}$`),
    component,
    params,
  });
  return this;
},