flemov1.5.7

Router & Route

라우트 매칭, 등록, 기본 옵션

<Router>는 루트 컨테이너예요. URL에 맞는 <Route>를 골라 렌더해요.

<Router>
  <Route path="/" element={<Home />} />
  <Route path="/posts/:slug" element={<Post />} />
</Router>

경로 패턴

경로 매칭은 path-to-regexp v8을 그대로 써요.

"/"; // 정확 매칭
"/posts/:slug"; // 단일 파라미터
"/users/:id/posts/:p"; // 다중 파라미터
"/files/*splat"; // 와일드카드

여러 경로를 한 컴포넌트에 매핑하려면 배열로 넘겨요.

<Route path={["/", "/home"]} element={<Home />} />

타입 안전한 라우트

RegisterRoute를 augment 하면 navigate.pushuseParams가 모두 타입 검증돼요. 한 파일에 모아서 선언하든, 각 페이지 파일에서 자기가 쓰는 라우트만 선언하든 — TypeScript가 모든 선언을 합쳐서 보기 때문에 어느 쪽이든 동작해요. 보통 <Router>를 마운트하는 파일 하단에 같이 두면 편해요.

App.tsx
declare module "flemo" {
  interface RegisterRoute {
    "/": undefined;
    "/posts/:slug": { slug: string };
    "/users/:id": { id: string };
  }
}

파라미터가 없는 경로는 undefined, 있는 경로는 그대로 shape를 적어요.

navigate.push("/posts/:slug", { slug: "hello" }); // ✅
navigate.push("/posts/:slug", { id: "1" }); // ❌ 타입 에러
navigate.push("/unknown"); // ❌ 타입 에러

Router 옵션

<Router initPath="/" defaultTransitionName="cupertino" transitions={[]} decorators={[]}>
  {/* routes */}
</Router>
Prop기본값설명
initPath"/"SSR에서 window.location이 없을 때 쓰는 경로
defaultTransitionName"cupertino"navigate.push가 전환을 지정하지 않았을 때의 기본 전환
transitions[]등록할 커스텀 전환
decorators[]등록할 커스텀 데코레이터

SSR

<Router>는 서버에서도 렌더링돼요. 다만 서버에는 window.location이 없어서 첫 렌더에 어떤 경로를 그릴지 직접 알려줘야 해요. 그게 initPath예요.

  • 서버: initPath에 해당하는 화면을 렌더해요. 지정하지 않으면 "/"예요.
  • 클라이언트: 마운트되면 window.location.pathname을 읽어 그대로 이어받아요.

서버가 받은 요청 경로를 그대로 넘기면 hydration mismatch 없이 첫 화면이 맞아요. 예를 들어 Next.js App Router에서는:

app/[[...slug]]/page.tsx
export default async function Page({ params }: { params: Promise<{ slug?: string[] }> }) {
  const { slug = [] } = await params;
  const initPath = "/" + slug.join("/");

  return <Router initPath={initPath}>{/* routes */}</Router>;
}

서버 렌더가 필요 없는 SPA(Vite, CRA 등)라면 initPath는 신경 쓰지 않아도 돼요. 클라이언트에서 바로 window.location.pathname을 읽어요.

이 페이지에서