티스토리 뷰

반응형

Next.js는 일반적인 리액트의 페이지 기반 라우팅과 다르게 파일 기반 시스템으로 되어있어, vscode 같은 통합개발환경에서 개발을 위해 폴더와 파일을 만들면 그 구조가 자연스럽게 라우팅에 활용되도록 해줍니다.
정적 라우팅과 동적 라우팅을 활용하는 방법을 알아보겠습니다.

next.js route

1.  정적 라우팅

정적 라우팅은 라우트가 빌드 타임에 결정되는 것을 의미합니다. 이 경우, 각 페이지에 대한 라우트가 사전에 정의되어 있으며, 사용자가 해당 페이지를 요청하면 라우팅이 발생합니다.
아래는 정적 라우팅 구조의 예시.

- pages
  - index.js
  - about.js
  - contact.js

위의 예시에서는 index.js, about.js, contact.js 파일이 각각 /, /about, /contact 경로로 이동됩니다.
 

2. 동적 라우팅

동적 라우팅은 라우트가 런타임에 결정되는 것을 의미합니다. 이 경우, URL의 일부분이 동적 매개변수로 처리되며, 이를 기반으로 페이지가 렌더링 됩니다.
아래는 동적 라우팅 구조의 예시.

pages
  - posts
    - [slug].js

위의 예시에서는 posts 폴더 내에 [slug].js 파일이 있으며, [slug]는 동적 매개변수입니다. 이 경우, /posts/hello-world URL은 slug = 'hello-world'로 처리되며, posts/[slug].js 파일이 렌더링 됩니다.
이와 같은 폴더 구조는 다양한 동적 라우팅 시나리오를 처리하기에 적합합니다.

3. 매개 변수 활용 - useRouter

next.js에서 동적 라우팅을 할 때, 매개변수를 서버로 전달하여 처리하는 방법을 알아보겠습니다.
동적 라우팅을 하기 위해서는, 파일 이름에 [대괄호]를 사용합니다. 예를 들어, [id].js라는 파일 이름을 사용하면, id라는 매개변수를 사용할 수 있습니다.

// pages/[id].js

import { useRouter } from 'next/router'

function Post() {
  const router = useRouter()
  const { id } = router.query

  return <p>Post: {id}</p>
}

export default Post

위의 코드에서는 useRouter()를 사용하여 router 객체를 가져온 후, router.query를 사용하여 매개변수 값을 가져옵니다.
그리고 서버에서 이 값을 받아오기 위해서는 getInitialProps를 사용할 수 있습니다.

// pages/[id].js

function Post({ data }) {
  return <p>Post: {data.title}</p>
}

Post.getInitialProps = async (ctx) => {
  const { id } = ctx.query
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`)
  const data = await res.json()

  return { data }
}

export default Post

위의 코드에서는 ctx.query를 사용하여 매개변수 값을 가져온 후, API를 호출하여 데이터를 가져옵니다. 이렇게 서버에서 매개변수 값을 받아온 후, 이 값을 req.body로 전달하여 처리할 수 있습니다.
이렇게 next.js의 동적 라우팅에서 매개변수를 서버로 전달하여 처리하는 방법을 알아보았습니다.
 
4. Catch-All 라우트
Catch-All 라우트란 next.js에서 제공하는 기능 중 하나로, 경로를 정의하지 않은 페이지를 처리하는 방법입니다. 예를 들어, /pages/[...slug].js 파일을 생성하면, /pages/a, /pages/a/b, /pages/a/b/c와 같은 모든 경로가 해당 파일로 라우트 됩니다.
이 기능은 동적으로 생성되는 페이지를 처리하는 데 유용합니다. 또한, 더 나은 SEO를 위해 URL 구조를 더욱 깔끔하게 만들어 줄 수 있습니다.
하지만, 이 기능을 사용할 때는 URL 구조를 신중하게 설계해야 하며, 잘못된 구조로 인해 사용자가 원하지 않는 페이지에 랜딩 할 수 있습니다. 따라서, 충분한 테스트와 검증을 거친 후에 이 기능을 사용하는 것이 좋습니다.

슬러그로 필터링해 보기

catch-all 라우트를 사용하여 데이터를 필터링하는 방법

// pages/[...slug].js

import { useRouter } from 'next/router';

const data = [
  { id: 1, name: 'Apple', category: 'Fruit' },
  { id: 2, name: 'Banana', category: 'Fruit' },
  { id: 3, name: 'Carrot', category: 'Vegetable' },
  { id: 4, name: 'Tomato', category: 'Vegetable' },
];

export default function FilterPage() {
  const router = useRouter();
  const { slug } = router.query; // slug는 배열 형태이다.

  // slug를 기반으로 데이터 필터링
  const filteredData = data.filter(item => {
    // 예시: slug[0]이 'category'이고, slug[1]이 카테고리 이름인 경우 해당 카테고리의 데이터만 필터링
    if (slug[0] === 'category' && slug[1] === item.category) {
      return true;
    }
    return false;
  });

  return (
    <div>
      <h1>Filtered Data</h1>
      <ul>
        {filteredData.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

위의 코드에서 data 배열은 필터링할 대상 데이터를 나타냅니다. **filteredData**는 data 배열을 slug를 기반으로 필터링한 결과를 저장합니다. 위의 예시에서는 **slug[0]**이 **'category'**이고 **slug[1]**이 카테고리 이름인 경우 해당 카테고리의 데이터만 필터링합니다.
예를 들어, /category/Fruit 경로로 접근하면 **filteredData**에는 **category**가 **'Fruit'**인 데이터만 포함됩니다.
실제 프로젝트에서는 필터링 조건과 데이터 구조에 따라 필터링 로직을 수정해야 할 수 있다. 이 예시는 단순한 필터링을 보여주기 위한 것이므로, 필요에 따라 해당 로직을 수정하여 원하는 방식으로 데이터를 필터링할 수 있습니다.
필요한 경우, 데이터 소스를 외부 API 호출이나 데이터베이스 쿼리 등으로 변경하여 데이터를 가져오고 필터링할 수도 있습니다.

5. Link - 'next/link'

Link 컴포넌트를 사용하여 페이지 간의 링크를 생성할 수 있습니다. href 속성에는 이동할 페이지의 경로를 설정해야 합니다. pathname 속성은 페이지의 경로를 나타내며, query 속성은 URL의 쿼리 파라미터를 설정합니다.

import Link from 'next/link';

const friends = [
  { id: 'suno', name: 'Super Normal' },
  { id: 'mark', name: 'Mark Morison' },
];

<ul>
  {friends.map((friend) => (
    <li key={friend.id}>
      <Link
        href={{
          pathname: '/friends/[id]',
          query: { id: friend.id, name: friend.name },
        }}
      >
        {friend.name}
      </Link>
    </li>
  ))}
</ul>

위의 예시에서 '/friends'은 이동할 페이지의 경로를 나타낸다. query 속성에는 객체 형태로 쿼리 파라미터를 설정할 수 있습니다. 예를 들어, id와 name이라는 쿼리 파라미터를 설정했습니다.
이렇게 Link 컴포넌트를 사용하여 페이지 간의 링크를 생성하면, 클릭 시 해당 페이지로 전환됩니다. 전환된 페이지에서는 query 파라미터를 사용하여 필요한 데이터를 가져올 수 있습니다.
이렇게 Next.js에서 Link와 href를 사용하여 pathname과 query를 설정하여 페이지 간의 내부 링크를 생성할 수 있습니다. 이를 통해 페이지 간의 전환과 쿼리 파라미터 전달을 간편하게 처리할 수 있습니다.
 

6. route.push() 개발적인 방법으로 페이지 이동

useRouter 훅을 사용하여 동적 경로 및 쿼리 파라미터를 활용하여 페이지 이동을 처리하는 예시

import { useRouter } from 'next/router';

const FriendPostsPage = () => {
  const router = useRouter();

  const { id, name } = router.query;

  const clickPostHandler = (postId: string) => {
    router.push({
      pathname: '/friends/[id]/[postId]',
      query: { id: id, postId: postId },
    });
  };

  return (
    <div>
      The Posts of a selected friend
      <p>{name}'s page</p>
      <button onClick={() => clickPostHandler('post1')}>Post A</button>
    </div>
  );
};

export default FriendPostsPage;

router.push를 사용하여 새로운 페이지로 이동합니다. 이때 pathname은 동적 경로를 나타내고, query는 쿼리 파라미터를 설정합니다. id와 postId는 이전에 가져온 id 값과 파라미터로 전달된 postId 값을 사용합니다.

반응형