게으른개발너D

Practice Project 4 - Catch All and 404 Pages 본문

개발/NextJS

Practice Project 4 - Catch All and 404 Pages

lazyhysong 2023. 12. 1. 16:28

 

1. Catch All

이제 catch-all URL을 만들어보자.

catch-all URL은 뭐든 캐치하는 URL이다.

우리가 이걸 쓰는 이유는 SEO에 좋게하기 위해서다.

영화제목을 url에 넣으려고 하는데, 한글이나 띄어쓰기같은 문자는 알파벳이 아닌 다른 문자열로 나오기 때문에 보기에도, SEO에도 별로 좋지 않다.

예를들어 'Spider-Man No Way Home'을 url에서 'Spider-Man+No+Way+Home'처럼 나오게 하려고 한다.

 

현재 [id].js 라고 설정해 놓은 파일 이름을 바꿀 것이다.

지금은 id라는 하나의 변수만 받고있다.

앞에 ...을 넣어서 [...id].js로 파일명을 변경해보자.

그럼 Spider-Man: No Way Home' 제목이 들어간 url로도 상세페이지에 접근할 수 있다.

 

[...id].js에서 router를 console.log로 확인해 보자.

query를 보면 id가 이제 string이 아니라 두개가 들어있음을 확인할 수 있다.

 

만약에 url을 localhost:3000/movies.Spider-ManNoWayHome/634649/12/12/12/12/1234/34/34 로 쳐서 들어갔다고 하자.

그럼 여전히 상세포기 페이지에 있으며, console.log를 보면 이렇게 나와있다.

 

catch-all을 썼으니 [...id]라고 하는건 바람직하지 못하므로 id 대신 params로 바꾸자.

[...params].js

 

이제 우리는 url을 /movies/영화제목/영화id 로 만들건데, 영화제목은 유저들에게 보여줄 것, 영화 id는 api에 요청을 보낼 때 사용할 것이다.

 

url 마스킹을 이용해서 index.js를 다시 고쳐보자.

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

pathname, query, as 부분을 모두 지우고 위처럼 수정해주었다.

제목에 Link로 적어놓았던 부분도 이와같이 바꿔주자.

 

index페이지에서 영화를 클릭해서 상세페이지로 들어가면 url이 이렇게 변해있다,

 

router에서 받은 값으로 [...params].js 페이지에 제목과 id를 사용해보자.

// [...params].js

import { useRouter } from 'next/router';

export default function Detail() {
  const router = useRouter();
  const [title, id] = router.query.params;
  return (
    <div>
      <h4>{title}</h4>
    </div>
  );
}

 

상세페이지로 들어가면 아주 잘 동작하고 있다.

영화 제목이 이제는 url에 encode 되어있다.

 

하지만 누가 incognito 모드에서 접속한다면 (index 페이지에서 상세페이지로 넘어오는 것이 아닌, url을 그대로 쳐서 상세페이지로 가는 것) server error가 발생한다.

해당 페이지가 벡엔드에서 pre-render 되기 때문이다.

server에는 router.query.params가 아직 존재하지 않는다.

 

그래서 해당 부분을 이렇게 고쳐주자,

// [...params].js

import { useRouter } from 'next/router';

export default function Detail() {
  const router = useRouter();
  const [title, id] = router.query.params || [];
  return (
    <div>
      <h4>{title}</h4>
    </div>
  );
}

 

이제 incognito  모드로 접속해서 에러 발생없이 화면이 잘 나온다.

이건 우리가 client-side rendering만 해줬기때문이다.

검색엔진은 소스코드 어디에도 title 텍스트를 찾을 수 없을 것이다.

 

절충점을 잘 찾아야하는데, index.js에서 한 것 처럼 getServerSideProps 함수를 쓸 수도 있다.

그럼 request에 대한 정보를 얻을 수 있고, 영화 제목도 얻을 수 있다.

// [...params].js

...

export function getServerSideProps(ctx) {
  console.log(ctx)
  return {
    props: {}
  }
}

일단은 빈 객체를 반환해 보자.

매개변수에 ctx를 적었는데, next.js가 server-side context를 제공해준다.

console.log로 확인해 보자.

server에서 파마미터 값으로 title과 id가 넘어왔음을 알 수 있다.

 

유저에게 loading 페이지를 보여주기 싫고, SEO에 아주아주 최적화되게 만들고 싶다면 이렇게 getServerSideProps를 사용하면 된다.

// [...params].js

...

export function getServerSideProps({ params: { params } }) {
  return {
    props: {
      params,
    },
  };
}

 

context 안에 params 안에 params가 들어있으니 저렇게 써주었다.

그리고 Detail component의 prop에 params를 넣어주자.

// [...params].js

export default function Detail({ params }) {
  const router = useRouter();
  const [title, id] = params || [];
  return (
    <div>
      <h4>{params.title}</h4>
    </div>
  );
}

 

이제 상세페이지를 확인하면 주로를 바로 치고 들어가더라도 백엔드에서 데이터를 가지고 오므로 title을 소스보기에서 확인할 수 있다.

 

 

 

 

 

 

2. 404 Pages

404페이지를 커스텀하자.

pages 폴더에 404.js 파일을 만들기만 하면 된다.

// 404.js

export default function NotFound() {
  return 'what are you doing here?';
}

 

 

 

 

 

 

 

 

 


출처

노마드코더

https://nomadcoders.co/nextjs-fundamentals

 

All Courses – 노마드 코더 Nomad Coders

초급부터 고급까지! 니꼬쌤과 함께 풀스택으로 성장하세요!

nomadcoders.co

 

Comments