티스토리 뷰

Catch-all URL 이란

아래 사진과 같이 url 뒤에 붙여진 parameter 값을 다 받아오는것을 말합니다.

 

위 URL 에 영화 제목을 넣어 SEO 최적화를 시켜줄겁니다.

 

이 방법을 사용하게 되면 영화의 제목을 바로 받아올 수 있을 뿐더러 홈페이지에서

클릭 후 상세페이지를 들어오지 않더라도 영화의 제목을 확인할 수 있게됩니다.

 

우선 index.js URL 라우팅을 다음과 같이 영화제목도 url에 들어갈 수 있도록 바꿔줍니다.

 

 

[...] 으로 Catch-All

그리고 이전에 만들었던 pages > movies > [id].js의 파일명을 [...params].js 로 바꿔줍니다.

여기서 id > params 로 바꾼 이유는 더이상 id의 파일명 보다는 catch all 할 url이 하나의 parameter query를 받아올것이 아니기때문에 더 적절한 params 로 바꾸어주었고 앞에 ...을 추가하게 되면 url 을 catch-all 하게 되어 router에서 query로 받아올 수 있습니다.

 

 

그리고 해당 파일에서 router을 console log를 찍어보면

다음과 같이 query의 값이 더이상 object형식의 string으로 반환을 시키지 않고 배열 형식의 값을 반환합니다.

 

 

 

배열 재 분할

배열 재 분할을 통해서 router query의 미리 이름을 정해두었던 params의 값을 받아오도록 하겠습니다.

다음과 같이 router.query.params의 Array의 길이가 2개라는것을 미리 알고 있기에

0번째 영화의 제목, 1번째 영화의 id 값을 다음과 같이 받아올 수 있습니다.

 

아래와 같이 params 안에 들어가있는것을 확실히 알고 있을때만 말이죠.

 

router.query.params : ["영화제목", "영화 id"]

 

// [...params].js
import { useRouter } from "next/router";
export default function Detail() {
  const router = useRouter();
  const [movieTitle, movieId] = router.query.params;
  return (
    <div>
      <h4>{movieTitle || "Loading..."}</h4>
    </div>
  );
}

home에서 영화를 클릭하고 들어오면 발생하지않지만 이것은 에러를 발생시킵니다.

 

 

왜냐면 서버에는 아직 router.query.params가 없고 아직 배열이 아니기 때문이죠.

 

재분할 에러 핸들링

재 분할과정에서 해당 값이 없을때 에러가 나지 않으려면 다음과 같은 문법을 사용하면 됩니다.

const [movieTitle, movieId] = router.query.params || [];​

그러면 해당 페이지에서 새로고침을 하여도 에러가 나지 않게됩니다.

 

 

 

getServerSideProps Context 

하지만 위의 방법보다 더 나은 SEO 경험을 만들수 있습니다.

 

그 이전에 브라우저에서 받아온 Source 파일을 살펴봅니다.

아래와 같이 영화의 제목이 포함되지 않은채로 html 파일을 받아옵니다.

 

html 파일에 영화 제목을 포함시킨 채로 받아오는 방법은 없을까요?

getServerSideProps Context라는것을 사용하면됩니다!

 

[...parmas].js 파일에 getServerSideProps() 함수를 추가해주고 인자값으로 ctx를 넣고 console을 찍어봅니다.

// [...params].js
import { useRouter } from "next/router";
export default function Detail() {
  const router = useRouter();
  const [movieTitle, movieId] = router.query.params || [];
  return (
    <div>
      <h4>{movieTitle || "Loading..."}</h4>
    </div>
  );
}

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

 

getServerSideProps함수에서 찍은 console.log는 실행시킨 cmd 창에서 확인할 수 있습니다.

다음 cmd 창의 사진과 같이 params.params 값으로 영화 제목과 id 를 볼 수 있습니다.

자 그럼 서버에서는 params 의 params값을 props로 넘겨주고,

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

클라이언트에서는 그 값을 받아서 처리해줍니다.

export default function Detail({ params }) {
  const router = useRouter();
  const [movieTitle, movieId] = params;
  return (
    <div>
      <h4>{movieTitle}</h4>
    </div>
  );
}

 

최종적인 [...params].js 코드입니다.

import { useRouter } from "next/router";
export default function Detail({ params }) {
  const router = useRouter();
  const [movieTitle, movieId] = params;
  return (
    <div>
      <h4>{movieTitle}</h4>
    </div>
  );
}

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

 

이전과 같이 영화 제목을 잘 보여줍니다.

 

또한 Source 파일을 보게되면 html 파일에도 영화 제목이 포함되어 파일을 받게됩니다.

 

 

위의 방식과 같이 하게되면 불 필요한 API 호출을 최소화 할 뿐더러 로딩속도,

SEO 최적화까지 노릴수 있는 장점들을 가져갈 수 있습니다.

댓글
최근에 올라온 글