[트러블슈팅] GitLab Pages에서 React Router 새로고침 시 404 에러 해결기

Innes·2025년 8월 5일

회사 프로젝트를 진행하면서 React + Tailwind 프로젝트GitLab Pages에 배포했는데,
라우팅과 관련된 문제가 발생했다. 로컬 개발 서버에서는 문제가 없었지만, 배포된 페이지에서 새로고침 시 404 에러가 뜨는 상황이었다.
이 글에서는 내가 겪은 문제 상황과 원인 분석, 해결책 비교, 그리고 최종적으로 HashRouter로 임시 해결한 과정을 정리한다.


1. 문제 상황

  • React 프로젝트를 GitLab Pages로 배포
  • 라우팅에 BrowserRouter 사용
  • 로컬 개발 서버에서는 라우팅 및 새로고침 모두 정상 동작
  • 문제: GitLab Pages 배포 후 특정 URL 직접 접근 또는 새로고침 시 GitLab 기본 404 페이지가 표시됨

증상

  • /dashboard 같은 URL을 직접 입력하면 GitLab의 404 UI 표시
  • 페이지 내에서 클릭으로 이동하면 UI 정상 작동
  • 이동 후 새로고침하면 다시 메인 페이지(/)로 리다이렉트됨
  • URL은 바뀌지만 React Router에서 페이지를 렌더링하지 못함

2. 원인 분석

  • GitLab Pages는 정적 호스팅으로 동작
  • 서버 측 라우팅 설정 불가 → 존재하지 않는 경로 요청 시 404 반환
  • React Router의 BrowserRouter는 HTML5 History API를 사용
  • 따라서 새로고침 시 서버에 직접 요청 → 서버는 해당 경로의 정적 파일 없음 → 404 발생

    dist 폴더를 확인해보자. index.html 하나만 있는걸 봐도 알 수 있다. gitlab pages는 정적 호스팅이기 때문에 링크를 전달해서 요청하면 배포주소는 index.html하나만 바라보고 있어서 '전달받은 링크같은 그런 파일은 없는데..?'라고 생각하고 404를 뱉어버리는 것이다.


3. 시도한 해결 방법들

방법 1: 404.html + sessionStorage 복원

  • 404.html에서 현재 경로를 sessionStorage에 저장
  • /로 리다이렉트 후 App.tsx에서 sessionStorage 값을 읽어 원래 경로로 복원

장점

  • URL 깔끔하게 유지 (/dashboard 그대로 사용)
  • React Router 그대로 사용 가능

단점

  • 존재하지 않는 URL도 메인 페이지로 리다이렉트 → SEO 문제
  • GitLab Pages의 404 응답이 항상 200으로 변환 → 에러 구분 불가
  • sessionStorage 복원 로직이 복잡하고 유지보수 어려움

방법 2: 404.html → index.html 유사 내용으로 처리 (sessionStorage 사용 안 함)

  • 404.htmlindex.html과 동일한 React 앱으로 구성
  • 사용자가 잘못된 URL을 직접 입력하면 404.html이 로드되고, React Router가 즉시 실행되어 해당 경로를 해석
  • 존재하지 않는 경로는 NotFoundPage로 처리, 존재하는 경로는 정상 라우팅

장점

  • sessionStorage 없이 자연스럽게 동작
  • 클릭/새로고침/직접 접근 모두 정상 작동

단점

  • 잘못된 URL도 200 상태로 서빙되어 SEO 문제
  • GitLab Pages 특성상 서버 측 404 구분 불가

방법 3: GitLab Pages CI 수정 (모든 경로 index.html로 fallback)

  • GitLab CI 설정에서 모든 요청을 index.html로 리다이렉트하도록 설정
  • 404.html 활용 없이 서버 레벨에서 우회

장점

  • URL 깔끔 유지
  • 별도 복원 로직 불필요

단점

  • GitLab Pages는 커스텀 리라이트 규칙을 지원하지 않음 (불가능에 가까움)
  • 결국 404.html 방식과 유사한 효과만 기대 가능

방법 4: HashRouter 사용

  • React Router에서 BrowserRouterHashRouter로 변경
  • URL이 /#/dashboard 형태로 변경됨
  • 서버는 # 이후 경로를 무시하므로 항상 index.html 반환
  • 클라이언트 라우팅은 해시 기반으로 정상 작동

장점

  • 가장 단순하고 빠른 해결책
  • GitLab Pages 특성과 100% 호환
  • 별도 서버 설정, 404.html 필요 없음
  • 새로고침, 직접 접근 모두 문제 없이 동작

단점

  • URL에 # 포함 → SEO에 불리
  • HTTP 상태 코드와 무관하게 항상 200 응답

4. 최종 선택: HashRouter

선택 이유

  • 빠른 배포 필요
    • 회사 프로젝트이고 GitLab Group 비공개 레포
    • Vercel/Netlify는 그룹 비공개 레포 무료 연결 불가
    • 유료 서비스 사용 불가한 상황
  • 임시 배포
    • 최종적으로는 AWS 등 서버 기반 배포로 이관 예정
    • SEO 문제는 이후 서버 배포 시 BrowserRouter로 복원하며 해결 가능
  • 적용 난이도 최소
    • BrowserRouter → HashRouter 변경만으로 문제 해결
    • 404.html 및 복원 로직 제거 가능

5. 적용 방법

1) main.tsx 수정

import { HashRouter } from 'react-router-dom';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>
);
profile
무서운 속도로 흡수하는 스펀지 개발자 🧽

0개의 댓글