리액트 라우터 돔: HashRouter와 BrowserRouter의 차이점

김현준·2025년 3월 24일

리액트 이모저모

목록 보기
28/31

프로젝트를 진행하면서 쿼리스트링을 감출 수 있을까? 라는 생각이 들었다.
그러다 리액트 라우터 돔의 HashRouter를 사용할 경우 그것이 가능하다는 것을 알았다.
HashRouterBrowserRouter의 차이점 그리고 왜 HashRouter를 사용할 경우 쿼리스트링이 주소창에 안 보이는 것처럼 보일 수 있는지를 알아보자.


Router 두 개의 기본 차이

구분BrowserRouterHashRouter
주소 형태/about/#/about
히스토리 API 사용pushState 사용안 씀
새로고침 가능O (서버 설정 필요)O (서버 설정 없이도 OK)
쿼리스트링주소창에 보임주소창 안 # 뒤에 포함됨

그럼 HashRouter일 때 쿼리스트링이 안 보인다는 게 무슨 뜻인가?

예를 들어 HashRouter를 쓰고 있고, 페이지네이션 클릭으로 아래와 같은 쿼리스트링을 넣는다고 하자:

setSearchParams({ pageNumber: '2' });

이렇게 하면 주소는 대략 이런 식으로 바뀐다:

http://localhost:5173/#/?pageNumber=2

그런데 이 ?pageNumber=2# 뒤에 포함되어 있어서 사용자 입장에서는 눈에 안 띈다

브라우저는 # 이후를 "해시(fragment)"라고 보고, 이 부분은 페이지의 특정 위치로 스크롤하거나 클라이언트 측 라우팅용으로만 사용된다.
서버는 이걸 아예 무시하고 보지 않는다.

즉, 눈에 잘 띄는 이 형태 👇 (BrowserRouter)

http://localhost:5173/page?pageNumber=2

이 아니라...

눈에 잘 안 띄는 이 형태 👇 (HashRouter)

http://localhost:5173/#/?pageNumber=2

결론: 왜 쿼리스트링이 안 보이는 것처럼 느껴지는가?

  1. HashRouter는 URL의 # 이후를 클라이언트 전용으로 쓰기 때문에
  2. ?pageNumber=2# 뒤에 붙어 있어서
  3. 사용자가 "주소가 안 바뀌었다"고 착각하기 쉽다.

HashRouter를 써야만 하는 경우엔?

그럴 땐 아래처럼 보면 된다:

http://localhost:5173/#/page?pageNumber=2
                 ▲▲▲▲ 이게 실제 주소고,
                      ▲▲▲ 이게 쿼리스트링이다

단지 # 뒤에 있기 때문에 눈에 잘 안 띌 뿐이다.

profile
기록하자

0개의 댓글