Skip to content

[Preview] 라우터 basename이 배포용 base로 고정된 앱은 프리뷰에서 빈 화면 #117

Description

@Danto7632

요약

Issue #111로 자산 경로는 해결됐지만, 앱이 라우터 basename을 배포용 base로 고정하면 자산이 전부 200으로 로드돼도 라우터가 아무것도 렌더하지 않아 화면이 빈 채로 남는다. 자산 로딩과 무관한 별개 층이며, 콘솔에 에러조차 남지 않아 진단이 어렵다.

메커니즘

GitHub Pages용 Vite 프로젝트의 정석 레시피가 원인이다:

<BrowserRouter basename={import.meta.env.BASE_URL}>

import.meta.env.BASE_URL은 빌드 타임에 base 값(/my-todo-app/)으로 인라인된다. 그런데 프리뷰에서 브라우저의 location.pathname/api/v1/previews/{sessionId}/{accessToken}/…이다.

react-router(6.30.4 dist/index.js:1212-1231 기준):

let trailingPathname = stripBasename(pathname, basename);
if (trailingPathname == null) return null;

if (locationContext == null) { return null; }

basename이 pathname의 접두사가 아니면 <Router>NOTHING을 렌더한다. 즉 빈 페이지.

basename을 지우는 것으로도 해결되지 않는다 — 이번엔 라우트 정의(path="/")와 실제 pathname이 어긋난다.

왜 구조적인가

프리뷰 URL은 /api/v1/previews/{sessionId}/{accessToken}/ 형태이고 accessToken은 매 열람마다 회전한다(Issue #77 G4). 따라서 앱의 basename을 프리뷰 URL에 맞추는 것은 불가능하다(빌드 타임에 알 수 없고, 회전할 때마다 재빌드해야 한다). 게이트웨이 프록시나 HTML rewrite로도 못 고친다 — 라우터는 서버 응답이 아니라 location.pathname을 보기 때문이다.

현재 영향 범위

2026-08-15 운영에서 관측된 앱은 해당 없음(실측: 번들 191KB에 my-todo-app 문자열도 import.meta 흔적도 없어 BASE_URL을 쓰지 않음). 즉 지금 당장 깨진 사용자는 확인되지 않았고, LLM이 라우터를 넣으면서 이 레시피를 따라 쓰는 순간 발현된다.

해결 후보

  1. 프리뷰 빌드에서 base를 중립화 — 배포가 하는 것과 같은 방식(npx vite build --base=/)을 프리뷰에도 적용하면 BASE_URL/가 되어 basename도 /가 된다. 근본 해법이지만 제약이 있다:
    • 프리뷰 빌드 경로는 npm run build 하드코딩(PreviewWorkspaceService.java:133-134)이고, npm run build -- --base=/체인 스크립트에서 위험하다 — npm은 인자를 스크립트 문자열 끝에 이어붙이므로 "vite build && cp dist/index.html dist/404.html" 같은 스크립트에서는 cp로 인자가 가서 빌드가 exit 1로 깨진다(실측 확인).
    • Agent CODE 경로에는 서버가 통제하는 빌드 호출 자체가 없다(LLM이 직접 npm run build 실행) — 이 경로는 이 대책으로 커버되지 않는다.
  2. 서빙 계층에서 base 경로를 실재화 — dist 안에 ln -s . <base> 자기참조 심볼릭 링크. 컨테이너 실측에서 문서/JS/CSS/SPA 라우트 4케이스가 모두 올바른 MIME으로 200이 됐고 CapDrop ALL에서도 링크 생성이 성공했다. 다만 이것도 pathname 접두사(/api/v1/previews/...)를 없애주지는 못하므로 basename 문제 자체는 해결하지 못한다 — 자산 문제의 대안일 뿐이다.
  3. 프리뷰 전용 오리진 분리(§2.29부터 예고된 백로그) + base 중립화 조합이 유일한 완전 해법이다.
  4. 최소 조치: CODE 프롬프트에 "라우터 basename을 배포 경로로 고정하지 말 것"을 명시하고, 프리뷰가 비어 있을 때 이 원인을 안내한다.

출처

다중 에이전트 조사(2026-08-15, Issue #111 해법 판정 과정)의 react-router 소스 실측 및 컨테이너 실측. 관측 앱의 번들 분석은 직접 수행.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions