Javascript

Remix 쉽게 배우기: 플랫 파일 기반 라우팅 완벽 가이드

드리프트2 2024. 9. 21. 13:29

Remix 쉽게 배우기: 플랫 파일 기반 라우팅 완벽 가이드

Remix 웹 프레임워크를 사용해 보셨나요?

 

Remix는 강력한 기능을 제공하지만, 그 중 하나인 플랫 파일 기반 라우팅이 처음에는 다소 복잡하게 느껴질 수 있습니다.

 

이 글에서는 초보자도 쉽게 이해할 수 있도록 Remix의 플랫 파일 기반 라우팅이 어떻게 작동하는지 자세히 설명하겠습니다.

 

다양한 예제 코드를 통해 실제로 어떻게 적용되는지도 함께 살펴보겠습니다.

 

시작해볼까요?

 

라우팅이란 무엇인가요?

웹 애플리케이션에서 라우팅은 사용자가 특정 URL을 방문했을 때 어떤 페이지나 콘텐츠를 보여줄지를 결정하는 과정입니다.

 

예를 들어, example.com/about에 방문하면 "About Us" 페이지가 표시되고, example.com/contact에 방문하면 "Contact Us" 페이지가 표시됩니다.

 

라우팅은 이러한 URL과 페이지 간의 연결 고리 역할을 합니다.

 

라우트와 라우터의 차이

  • 라우트(Routes): 특정 URL 경로를 의미합니다. 예를 들어, /home, /about 등이 라우트입니다.
  • 라우터(Router): 이러한 라우트를 관리하고, 사용자가 특정 라우트에 접근할 때 맞는 페이지를 렌더링해주는 도구입니다.

 

Remix의 플랫 파일 기반 라우팅이란?

Remix는 파일 시스템을 기반으로 라우트를 자동으로 생성하는 플랫 파일 기반 라우팅 방식을 사용합니다.

 

이는 프로젝트의 app/routes 폴더에 파일을 추가하면, 그 파일이 자동으로 하나의 라우트가 된다는 의미입니다.

 

폴더 구조를 통해 URL 경로를 쉽게 관리할 수 있습니다.

 

플랫 파일 기반 라우팅의 장점

  1. 간편한 라우트 생성: 별도의 설정 없이 파일을 추가하기만 하면 라우트가 생성됩니다.
  2. 가독성 높은 구조: 파일과 폴더의 구조가 URL 경로와 일치하여 프로젝트 구조를 이해하기 쉽습니다.
  3. 유연성: 다양한 유형의 라우트를 쉽게 추가하고 관리할 수 있습니다.

 

기본 라우트 생성하기

플랫 파일 기반 라우팅의 가장 기본적인 사용법부터 시작해보겠습니다.

 

루트 라우트 설정

app/root.tsx 파일은 모든 Remix 애플리케이션의 루트 라우트입니다.

 

전체 애플리케이션의 레이아웃과 공통 요소를 정의합니다.

// app/root.tsx
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "remix";

export default function Root() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet /> {/* 자식 라우트가 여기에 렌더링됩니다 */}
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

 

간단한 페이지 라우트 추가하기

 

이제 app/routes 폴더에 새로운 파일을 추가해보겠습니다.

 

예를 들어, /about 페이지를 만들고 싶다면 app/routes/about.tsx 파일을 생성합니다.

// app/routes/about.tsx
export default function About() {
  return (
    <div>
      <h1>About Us</h1>
      <p>이 페이지는 우리 회사에 대한 정보를 제공합니다.</p>
    </div>
  );
}

 

이제 브라우저에서 http://localhost:3000/about에 접속하면 위의 내용을 볼 수 있습니다.

 

동적 라우트 만들기

플랫 파일 기반 라우팅은 동적인 URL도 쉽게 처리할 수 있습니다.

 

예를 들어, 사용자의 프로필 페이지를 만들고 싶다면, URL에 따라 다른 사용자의 프로필을 보여줘야 합니다.

 

동적 세그먼트 사용하기

동적 라우트를 생성하려면, 파일 이름에 $ 기호를 사용합니다.

 

예를 들어, 사용자 이름을 동적으로 받는 프로필 페이지를 만들려면 app/routes/profile.$username.tsx 파일을 생성합니다.

// app/routes/profile.$username.tsx
import { useParams } from "remix";

export default function UserProfile() {
  const { username } = useParams();

  return (
    <div>
      <h1>{username}님의 프로필</h1>
      <p>여기는 {username}님의 개인 정보 페이지입니다.</p>
    </div>
  );
}

 

이제 http://localhost:3000/profile/john이나 http://localhost:3000/profile/jane과 같은 URL로 접근하면, 각각의 사용자 이름이 페이지에 표시됩니다.

 

네스티드 라우트(Nested Routes) 활용하기

네스티드 라우트를 사용하면 부모 라우트 내에 자식 라우트를 설정하여 더 복잡한 레이아웃을 구현할 수 있습니다.

 

이는 큰 애플리케이션에서 페이지를 논리적으로 분리할 때 유용합니다.

 

폴더와 파일 구조로 네스티드 라우트 설정

예를 들어, concerts 관련 페이지를 만들고 싶다면 app/routes/concerts 폴더를 생성하고, 그 안에 여러 파일을 추가합니다.

app
└── routes
    └── concerts
        ├── _index.tsx
        ├── trending.tsx
        └── [city].tsx
  • _index.tsx: /concerts 경로에 해당하는 기본 페이지입니다.
  • trending.tsx: /concerts/trending 경로에 해당합니다.
  • [city].tsx: 특정 도시의 콘서트를 보여주는 동적 라우트입니다. 예를 들어, /concerts/seoul.

예제 코드

// app/routes/concerts/_index.tsx
export default function ConcertsIndex() {
  return (
    <div>
      <h1>콘서트 목록</h1>
      <p>가장 인기 있는 콘서트를 확인하세요.</p>
    </div>
  );
}

// app/routes/concerts/trending.tsx
export default function TrendingConcerts() {
  return (
    <div>
      <h1>인기 있는 콘서트</h1>
      <p>현재 가장 화제가 되는 콘서트 목록입니다.</p>
    </div>
  );
}

// app/routes/concerts/[city].tsx
import { useParams } from "remix";

export default function CityConcerts() {
  const { city } = useParams();

  return (
    <div>
      <h1>{city}의 콘서트</h1>
      <p>{city}에서 열리는 모든 콘서트를 확인하세요.</p>
    </div>
  );
}

 

이제 http://localhost:3000/concerts, http://localhost:3000/concerts/trending, http://localhost:3000/concerts/seoul 등 다양한 URL로 접근할 수 있습니다.

 

선택적 세그먼트(Optional Segments) 사용하기

경로의 일부를 선택적으로 만들고 싶을 때는 괄호(())를 사용합니다.

 

예를 들어, 언어 선택을 경로에 포함시키고 싶을 때 유용합니다.

예제: 언어 선택 경로

app
└── routes
    └── ($lang)._index.tsx
// app/routes/($lang)._index.tsx
import { useParams } from "remix";

export default function HomePage() {
  const { lang } = useParams();

  return (
    <div>
      <h1>{lang ? `${lang} 버전` : "기본"} 홈 페이지</h1>
      <p>여기는 홈 페이지입니다.</p>
    </div>
  );
}

 

이제 http://localhost:3000/http://localhost:3000/en 모두 홈 페이지를 렌더링하지만, 언어에 따라 다른 내용을 표시할 수 있습니다.

 

스플랫 라우트(Splat Routes) 활용하기

모든 경로를 포괄하고 싶을 때는 스플랫 라우트를 사용합니다. 이는 거의 모든 경로와 일치하는 라우트를 생성합니다.

예제: 파일 미리잡기

app
└── routes
    └── $.tsx
// app/routes/$.tsx
import { useMatches } from "remix";

export default function CatchAllRoute() {
  const matches = useMatches();
  return (
    <div>
      <h1>404 - 페이지를 찾을 수 없습니다.</h1>
      <p>요청하신 {matches.at(-1)?.pathname} 페이지는 존재하지 않습니다.</p>
    </div>
  );
}

 

이렇게 하면 존재하지 않는 모든 경로에 대해 404 페이지를 표시할 수 있습니다.

 

요약

Remix의 플랫 파일 기반 라우팅은 파일과 폴더 구조를 통해 직관적으로 라우트를 관리할 수 있게 해줍니다.

 

기본 라우트에서부터 동적 라우트, 네스티드 라우트, 선택적 세그먼트, 스플랫 라우트까지 다양한 라우팅 방식을 지원하여 복잡한 웹 애플리케이션도 쉽게 구축할 수 있습니다.

 

이 가이드를 통해 Remix의 라우팅을 보다 쉽게 이해하고, 실제 프로젝트에 적용해보세요!