게으른개발너D

Practice Project 3 - Dynamic Routes 본문

개발/NextJS

Practice Project 3 - Dynamic Routes

lazyhysong 2023. 11. 30. 18:21

 

1. Dynamic Routes

Dynamic URL을 어떻게 다루는지 알아보자,

지금까지는 Home과 About 페이지인, / 와 /about 두가지 url이 있다.

영화 상세보기 페이지처럼 url에 변수를 넣는 방법에 대해 알아보려고한다.

 

create-react-app의 react-router-dom에서는 해당 url은 예를들어 이런식으로 작성한다,

/movies/:id

이렇게 하면 reate-router-dom은 :id 부분이 변수라는 걸 인식한다.

 

1.1 next.js pages url

next.js에는 router가 없으므로 이런걸 하는 다른 방법이 당연히 존재한다.

 

pages 디렉토리에서 오직 폴더와 이름가지고만 만들 것이다,

/movies/all 이라는 url을 만들고싶다면 pages 폴더에 movies 폴더를 만든 후 새로운 파일을 만들어, 그 파일 이름은 all.js로 지으면 된다.

/movies 라는 url을 만들고싶다면?

pages 폴더에 movies.js라는 파일을 만들면 된다. 하지만 /movies/all 이라는 url을 가지고 있는 경우가 있기때문에 movies 폴더 안에 index.js 파일을 만들면 된다.

 

1.2 변수 url

변수를 가지는 url 페이지를 만드는 것 또한 당연히 pages 폴더 안에 만든다.

/movies/:id 라는 url을 만들고 싶다면 movies 폴더 안에 대괄호를 열어 변수를 넣은 이름의 파일을 만들면 된다.

예를들어 movies 안에 [id].js 파일을 만들었다.

 

// [id].js

import { useRouter } from 'next/router';

export default function Detail() {
  const router = useRouter();
  console.log(router);
  return 'detail';
}

 

detail 파일을 만들었는데, 여기서 router를 콘솔로 찍으면 어떻게 나오는지 보자.

/movies/654654 로 이동해 보자.

 

console을 보면 query를 볼 수 있는데, query에는 id가 있고 url에 있는 것과 같다.

 

 

 

 

 

2. Movie Detail

2.1 Link

영화 목록을 불러왔던 index.js에서 next/link의 Link를 import 해오고 영화를 Link로 감싸주자.

 

// index.js

import Link from 'next/link';

function Home({ results }) {
  return (
    <div className="container">
      <Seo title="Home" />
      {!results && <h4>Loading..</h4>}
      {results?.map((movie) => (
        <Link href={`/movies/${movie.id}`} key={movie.id}>
          <div className="movie">
            <img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
            <h4>{movie.original_title}</h4>
          </div>
        </Link>
      ))}
    </div>
  );
}

 

이제 영화를 클릭하면 아이디에 해당되는 상세보기 페이지로 이동한다.

 

Link는 영화 제목만 감싸주도록 바꿔주고, 이미지를 클릭했을 때도 상세보기 페이지로 이동하도록 다른 navigating 방법을 알아보자.

 

2.2 router hook

useRouter를 실행시켜주자.

// index.js

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

function Home({ results }) {
  const router = useRouter();
  const handleClick = (id) => {
  	router.push(`/moives/${id}`);
  };
  return (
    <div className="container">
      <Seo title="Home" />
      {!results && <h4>Loading..</h4>}
      {results?.map((movie) => (
        <div 
          onClick={() => handleClick(movie.id)} 
          className="movie" 
          key={movie.id}
        >
          <img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
          <h4>
            <Link href={`/movies/${movie.id}`}>
              {movie.original_title}
            </Link>
          </h4>
        </div>
      ))}
    </div>
  );
}

 

div를 클릭하면 페이지를 이동시킬 handleClick이라는 함수를 만든다.

useRouter를 이용하여 navigating을 하는 방법은 push를 사용하는 것이다.

router.push(이동할 url)

 

 

2.3 rewrite

이제 api key를 숨기기 위해서 next.config.js로 가서 rewrite를 하자.

  async rewrites() {
    return [
      {
        source: '/api/movies',
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
      },
      {
        source: '/api/movies/:id',
        destination: `https://api.themoviedb.org/3/movie/:id?api_key=${API_KEY}`,
      },
    ];
  },

 

이전에 작성했던 rewrite 바로 밑에 상세보기를 불러올 api 주소를 작성해주면 된다.

중요한건, source에서 :id라고 적었으면 destination에서도 :id라고 적어야한다! 들어가는 변수 명칭을 똑같이 해줘야하는 것!

 

2.4 push의 다른 기능 (as)

router.push 와 Link를 사용하는 것 말고도 url에 정보를 숨겨서 보내는 방법이 있다.

우리는 url에서 url로 state를 넘겨주는 방법을 공부할 것이다.

그리고 그걸 유저로부터 숨기는 방법도 배울 것이다.

 

router.push를 할 때 url을 string으로 보낼 수도 있지만 객체로 보내줄 수도 있다.

url은 url이고, as는 필수는 아니지만 as는 브라우저의 url을 마스킹할 것이다.

 

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

 

push 안에 object를 열고 pathname과 query에 위와같이 작성해주었다.

그리고 영화 이미지를 클릭하여 이동하면 해당 movies의 영화 id 경로로 이동한다,

url 뒤쪽에는 위에서 작성해주었던 영화에 대한 정보를 담고있는 query를 확인할 수 있다.

 

별로 보기 좋지 않으므로 해당 부분을 url에 보이지 않도록 숨길 것이다.

 

push 인수를 넣는 곳에 콤마를 한 후 as에 관한 인수를 작성해주자.

브라우저에 보일 url을 써준다.

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

 

이제 영화 이미지를 클릭하고 해당 페이지로 이동해보면 url은 as 부분에 설정해 놓은 /moives/id 규칙으로 보여진다.

근데 router를 들여다보면 우리가 담아둔 데이터를 확인할 수도 있다!

 

as로 url을 다르게 보여주자.

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

이렇게 하면 url은 /movies/영화제목 으로 보일 것이다.

 

// [id].js

import { useRouter } from 'next/router';

export default function Detail() {
  const router = useRouter();
  return (
    <div>
      <h4>{router.query.title || 'Loading...'}</h4>
    </div>
  );
}

이렇게하면 query로 넘겨줬던 title을 볼 수 있다.

 

 

router.push 말고도 Link 안에서도 같은 기능을 쓸 수 있다. 이런식으로!

<Link 
  href={{
    pathname: `/movies/${movie.id}`,
    query: {
      title: movie.title,
    }
  }}
  as={`/movies/${movie.title}`}
>

</Link>

 

 

 

 

3. Catch All

 

 

 

 

 

 

 

 

4. 404 Pages

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Comments