본문 바로가기

Frontend/Next

[NextJS] NextJS 시작하기 - 7. 다이나믹 라우팅 & 페이지 이동

반응형

1. Routes

NextJS의 개요를 다루면서, pages 폴더에 대해 살펴본 적이 있지만, 오늘은 더 자세한 기능을 볼 것이다.

pages는 페이지 라우팅을 자동으로 설정해주는 폴더로, 정적 라우팅은 물론 동적 라우팅도 가능하다.

 

아래 표를 통해 사용법을 확인하자.

pages 하위 폴더 구조 URL
pages/index.js /
pages/about.js /about
pages/movies/index.js /movies
pages/movies/all.js /movies/all
pages/movies/[id].js /movies/12

 

동적 라우팅은 [변수].js 파일을 통해 설정할 수 있다.

pages/movies/[id].js 에서는 id를 변수의 이름으로 설정한 것이고, useRouter를 통해 확인해 보면, query에 id라는 이름의 객체가 있는 것을 볼 수 있다.

 

 

 

2. 페이지 이동하는 방법

페이지 간 이동하는 방법 두 가지를 살펴볼 것이다.

 

1) Link 

  • index.js 페이지의 영화 컨테이너를 Link로 감싼다.
  • 하지만, 이는 HTML 구조에 반하는 것이다. (a 태그 안에는 텍스트가 들어가야 함)
<Link href={`/movies/${movie.id}`} key={movie.id}>
  <a>
    <div className='movie'>
      <img
        src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
      />
      <h4>{movie.original_title}</h4>
    </div>
  </a>
</Link>

 

2) router.push

  • onClick 이벤트를 활용해 라우팅을 임의로 설정해준다.
  • 이를 위해 useRouter의 push를 활용한다.
  const router = useRouter();
  const onClick = (id) => {
    router.push(`/movies/${id}`);
  };
  
  return (
    <div className='container'>
      <Seo title='Home' />
      {results?.map((movie) => (
        <div
          onClick={() => onClick(movie.id)}
          className='movie'
          key={movie.id}
        >
          ...
        </div>
      ))}
    </div>
  );

 

URL로 state를 넘기기

router.push에 영화 제목을 넘기고 싶으면 다음과 같이 작성하면 된다. 

이 경우 유저가 wow라는 영화를 클릭하면 /movies/1212?title=wow 가 브라우저 URL로 넘어간다.

(단, 이렇게 state를 넘길 경우 직접 해당 페이지로 접근하고나 새로고침을 하는 경우 데이터가 존재하지 않아 정상적인 페이지가 보이지 않는다. 이에 대한 별도의 처리를 해줘야 한다)

  const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`,
        query: {
          title,
        },
      },
    );
  };

 

브라우저의 URL을 마스킹하기

push는 다양한 옵션이 있다. 그증 as를 활용하면 브라우저의 URL을 마스킹할 수 있다.

위 경우 유저가 보는 URL에 쿼리가 담겨있었는데, 이를 원치 않을 경우 as를 사용해 숨기면 된다!

아래와 같이 push에 전달한 객체 다음 URL을 써주면 유저는 저 URL을 보게 된다. (/movies/1212)

  const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`,
        query: {
          title,
        },
      },
      `/movies/${id}`
    );
  };

 

최종 코드

import Link from 'next/link';
import { useRouter } from 'next/router';
import Seo from '../components/Seo';

export default function Home({ results }) {
  const router = useRouter();
  const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`,
        query: {
          title,
        },
      },
      `/movies/${id}`
    );
  };
  return (
    <div className='container'>
      <Seo title='Home' />
      {results?.map((movie) => (
        <div
          onClick={() => onClick(movie.id, movie.original_title)}
          className='movie'
          key={movie.id}
        >
          <img src={`https://image.tmdb.org/t/p/w500`} />
          <Link
            href={{
              pathname: `/movies/${movie.id}`,
              query: {
                title: movie.original_title,
              },
            }}
            as={`/movies/${movie.id}`}
          >
            <a>
              <h4>{movie.original_title}</h4>
            </a>
          </Link>
        </div>
      ))}
    </div>
  );
}
반응형