React Router의 HashRouter 알아보기

JJ·2023년 3월 14일
5

경험

목록 보기
1/4
post-thumbnail

해쉬라우터를 사용하게된 이유


영상편집 툴의 대표적인 Adobe Premiere Pro에서 동작하는 플러그인을 개발중인데 해당 플러그인은 HTML, CSS, JavaScript로 개발할 수 있다. 따라서 React환경을 구축해서 빌드하였다. 하지만 React App은 클라이언트 사이드 렌더링을 통해 서버에서 파일을 받아온다.하지만 Adobe 플러그인 같은경우에는 파일형태로 로컬 환경에서 실행되기 때문에 BrowserRouter대신 HashRouter를 사용하게되었다.

로컬에서 HTML 파일을 열면 일반적으로 file:// 프로토콜을 사용하는데 브라우저는 보안상의 이유로 file:// 프로토콜에서 일부 기능을 사용할 수 없도록 제한한다. 반면 HashRouter는 file:// 프로토콜에서도 정상적으로 작동한다.

처음에 이러한 사실을 모르고 BrowserRouter를 사용하여 라우팅을 했는데, 빌드하고 난 뒤 파일로 열어보니 라우팅이 제대로 되지 않은 이슈가 발생했다. 따라서 file:// 프로토콜에서 라우팅 기능을 사용하기 위해 HashRouter를 사용하였다.

HashRouter를 사용하면 위와같이 파일 형태로 Adobe Premiere Pro에서 플러그인이 열리게 된다.

웹페이지에서 해쉬(#)란?


우선 리액트에서 HashRouter를 알기 전 웹페이지에서의 해쉬부터 알아보자.

웹페이지에서 해쉬란 URL의 일부분으로 사용되는 문자열이다. 보통은 URL의 끝에 #과 함께 붙어서 사용되는데 해쉬는 서버로부터 새로운 페이지를 요청하지 않고도, 웹페이지 내에서 특정 영역을 식별하고 이동하는 것을 가능케 한다. 예를 들어, 웹페이지 내의 특정 섹션으로 이동할 때 해당 섹션의 ID값을 URL 끝에 #과 함께 붙인 해쉬로 지정한다면, 이 링크를 클릭했을 때 웹페이지는 해당 섹션으로 스크롤이 된다.

리액트에서 HashRouter란?


HashRouter는 React Router에서 제공하는 라우터 컴포넌트 중 하나로, URL의 해쉬값을 사용하여 페이지를 관리한다. 브라우저에서 URL의 해쉬값이 변경되면 HashRouter는 해당 경로와 일치하는 컴포넌트를 렌더링한다.

HashRouter의 동작 원리


github 코드를 보면 아래와 같다.

export interface HashRouterProps {
  basename?: string;
  children?: React.ReactNode;
  window?: Window;
}

/**
 * A `<Router>` for use in web browsers. Stores the location in the hash
 * portion of the URL so it is not sent to the server.
 */
export function HashRouter({ basename, children, window }: HashRouterProps) {
  let historyRef = React.useRef<HashHistory>();
  if (historyRef.current == null) {
    historyRef.current = createHashHistory({ window, v5Compat: true });
  }

  let history = historyRef.current;
  let [state, setState] = React.useState({
    action: history.action,
    location: history.location,
  });

  React.useLayoutEffect(() => history.listen(setState), [history]);

  return (
    <Router
      basename={basename}
      children={children}
      location={state.location}
      navigationType={state.action}
      navigator={history}
    />
  );
}

해당 코드에서는 createHashHistory 함수를 이용하여 history 객체를 생성하고, 이를 Router 컴포넌트의 history prop으로 전달한다. createHashHistory 함수는 history 패키지에서 제공하는 함수로, HashRouter의 내부에서 URL 주소를 읽어 들이고, 라우팅 처리를 담당한다.

HashRouterBrowserRouter와 달리, 브라우저의 URL이 변경될 때마다 페이지를 새로 로딩하지 않고, history 객체를 이용하여 React 애플리케이션 내에서 라우팅을 처리한다. 이를 통해 SPA에서의 페이지 전환 속도를 빠르게 만들어 준다.

예를 들어, 아래와 같은 코드에서 HashRouter 컴포넌트는 URL의 해쉬값을 이용하여 페이지를 관리한다.

import { HashRouter, Route, Switch } from "react-router-dom";

function App() {
  return (
    <HashRouter>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </Switch>
    </HashRouter>
  );
}

그러면 http://example.com/#/about 와 같은 URL을 가지는 페이지를 만들고 싶을 때 사용할 수 있다.

HashRouter의 성능


HashRouter는 URL의 해쉬값을 이용하기 때문에, 브라우저가 페이지를 캐싱할 수 있어서 성능이 우수하다. 또한, 페이지가 새로고침되지 않고도 컴포넌트가 변경되므로, UX가 매우 빠르고 부드럽다. 그러나 HashRouter는 URL의 해쉬값을 사용하기 때문에, 검색엔진최적화(SEO)에는 매우 취약하다. 따라서 SEO를 중요시 하는 웹 앱에서는 HashRouter대신 BrowserRouter를 사용하는 것이 좋다.

브라우저가 해쉬값을 읽는 원리


웹 브라우저는 URL의 해쉬값(’#’) 이후의 문자열을 프래그먼트 식별자로 간주한다. 일반적으로 해쉬값이 변경되면 hashchange라는 이벤트가 발생하는데 이 이벤트를 통해 javascript에서 해당 이벤트를 감지하고 필요한 동작을 수행할 수 있다.

window.addEventListener("hashchange", function() {
  // 해시값이 변경될 때 수행할 동작
  var newHash = window.location.hash;
  console.log("해시가 변경되었습니다: " + newHash);
  // 여기에 적절한 처리 로직 추가
});

보통 이런 이벤트를 자주 활용하는 예시는 특정 섹션에 해쉬URL을 설정하고 해당 섹션으로 스크롤링하는데에 많이 사용된다.

0개의 댓글