[NextJS] params๊ณผ SEO

guยท2023๋…„ 7์›” 24์ผ
0

Next.js

๋ชฉ๋ก ๋ณด๊ธฐ
12/13
post-thumbnail

๐Ÿ’ป URL์ฃผ์†Œ์— item ํƒ€์ดํ‹€ ๋„ฃ๊ธฐ

๐Ÿ–ค Params & SEO์ตœ์ ํ™”์‹œํ‚ค๊ธฐ

  • NextJS My-App๊ตฌ์กฐ

    ์—ฌ๊ธฐ์„œ ๋ด์•ผํ•  ๊ฒƒ์€ index.js์™€ [...params].js๋‹ค.
    ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰์—”์ง„ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด url์ฃผ์†Œ์— ์•„์ดํ…œ ์ •๋ณด(ํƒ€์ดํ‹€ ๋“ฑ)๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋„ฃ์–ด๋‘๋ฉด ๋งŽ์ด ์‚ฌ๋žŒ๋“คํ•œํ…Œ ์šฐ๋ฆฌ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋…ธ์ถœ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • index.js
<script>
import Head from "next/head";
import Link from "next/link";
import Seo from "../../component/Seo";
import { useState, useEffect } from "react";
import { useRouter } from "next/router";

export default function Home({ results }) {
    const router = useRouter();
    const onClick = (id, title) => {
        router.push(`/movies/${title}/${id}`);
    };
    console.log(results);
    return (
        <div className="container">
            <Seo title="Home" />

            {results?.map((item) => (
                <div onClick={() => onClick(item.id, item.original_title)} className="movie" key={item.id}>
                    <img style={{ width: "300px", height: "450px" }} src={`https://image.tmdb.org/t/p/w500${item.poster_path}`} />
                    <h4>
                        <Link href={`/movies/${item.original_title}/${item.id}`}>{item.original_title} </Link>
                    </h4>
                </div>
            ))}
          </div>
</script>
  • [...params].js
<script>
import { useRouter } from "next/router";
import Seo from "../../../component/Seo";

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

export function getServerSideProps({ params: { params } }) {
    return {
        props: {
            params,
        },
    };
}
</script>

์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ ์šฉํ–ˆ์„ ์‹œ ํŽ˜์ด์ง€์†Œ์Šค์—์„œ ์šฐ๋ฆฌ์˜ ์•„์ดํ…œ ์ •๋ณด๊ฐ€ ๋‚˜์˜ค๋Š”์ง€ ํ™•์ธํ•ด๋ณธ ๊ฒฐ๊ณผ

์ž˜ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋˜ํ•œ params์— ํฌํ•จ๋œ title์ด Seo์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ๋˜์–ด ์•„์ดํ…œ ์ •๋ณด๊ฐ€ ์›น Head์™€ url์ฃผ์†Œ์— ์ •์ƒ์ ์œผ๋กœ ๋‚˜์˜ค๋Š” ๊ฒƒ๋„ ํ™•์ธํ• ์ˆ˜์žˆ๋‹ค.

๐Ÿ’ก ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’์ด [...params].js์— ์ „๋‹ฌ๋˜๋Š” ์ด์œ 

index.js ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ์•„์ดํ…œ์˜ title๊ณผ id์ •๋ณด๋ฅผ [...params].js์— ๋ณด๋‚ด๋Š” ๋ถ€๋ถ„์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋‚ด๊ณ ์‹ถ์€ ์•„์ดํ…œ์ •๋ณด๋“ค์€ ์ž˜์ „๋‹ฌ๋œ๊ฒƒ์„ ๊ฒฐ๊ณผ์‚ฌ์ง„์œผ๋กœ ๋ณผ์ˆ˜์žˆ์—ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’๋“ค์ด [...params].js์— ๋ณด๋‚ด์งˆ์ˆ˜์žˆ์—ˆ๋˜ ๊ฒƒ์ผ๊นŒ?

โ— ํ•ด๋‹น ํ˜•์‹์˜ urlํŽ˜์ด์ง€๋ฅผ ์ •์˜ํ•œ [...params].js ํŒŒ์ผ์˜ ์ด๋ฆ„์ธ ์ฆ‰, 'params'๋ผ๋Š” ๋ณ€์ˆ˜์— ๋ฐฐ์—ด ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • [...params].js (console๋กœ ํ™•์ธํ•ด๋ณด๊ธฐ)
<script>
import { useRouter } from "next/router";
import Seo from "../../../component/Seo";

export default function Detail({ params }) {
    const router = useRouter();
    const [title, id] = params || [];
    console.log("params์—์ €์žฅ๋œ๊ฐ’", params);
    return (
        <div>
            <Seo title={title} />
            <h4>{title || "Loading..."}</h4>
        </div>
    );
}
</script>
  • console

    ํƒ€์ดํ‹€๊ณผ id๊ฐ€ params์— ๋ฐฐ์—ดํ˜•์‹์œผ๋กœ ์ €์žฅ๋œ๊ฒƒ์„ ์•Œ์ˆ˜์žˆ๋‹ค.

๐Ÿ–ค ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ•

ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—์„œ
1. router๋ฅผ ์ด์šฉํ•ด ๋ฐ›์•„์˜ค๋Š” ๋ฐฉ๋ฒ•

๋‹ค๋งŒ, router๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด js์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ†ตํ•ด ๋ผ์šฐํ„ฐ๋ฅผ ํ˜•์„ฑํ•˜๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•จ.
๊ทธ๋ž˜์„œ ๋งŒ์•ฝ router๋ฅผ ์ƒ์„ฑํ•ด์„œ, router๋ฅผ ํ†ตํ•ด params ๊ฐ’์„ ๋ฐ›์•„์˜ค๋ ค๋ฉด
( const [title, id] = router.query.params )
, ์ฒ˜์Œ์—๋Š” ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.
์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š” ์ด์œ ๋Š”, router๊ฐ€ ์—†์œผ๋‹ˆ, router.query.params ๊ฐ’๋„ ์–ป์„ ์ˆ˜ ์—†๋Š”๋ฐ,
const [title, id]=router.query.params; ์‹์œผ๋กœ title์ด๋‚˜ id ๋ณ€์ˆ˜์—, ์—†๋Š” ๊ฐ’์„ ํ• ๋‹นํ•˜๋ ค ํ•˜๋‹ˆ
์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค.
๊ทธ๋ž˜์„œ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋นˆ ๋ฐฐ์—ด์„ ์ด์šฉํ•œ ๊ฒƒ์ด๋‹ค.
const [title, id] = router.query.params || [];
์กฐ๊ธˆ ์‹œ๊ฐ„์ด ์ง€๋‚˜ router๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด, ์„œ๋ฒ„์—์„œ ๊ฐ„์งํ•˜๊ณ  ์žˆ๋Š” params๊ฐ์ฒด ๊ฐ’์„ router.query.params๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

2. rouer์ด์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹ค์ด๋ ‰ํŠธ๋กœ server๋กœ ๋ถ€ํ„ฐ ๋ฐ›์•„์˜ค๋Š” ๋ฐฉ๋ฒ•

<script>
export function getServerSideProps(**{params: {params} }**) {

         return { props: {params} };

}
</script>

์ด๋Š” {params: {params} ๊ฐ์ฒด๋ฅผ ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ๋ฐ›์•„์˜ค๊ณ , ํ˜„์ œ ํŽ˜์ด์ง€์— props๋กœ {params}๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

<script>
export default function Detail({ params }) {
    const router = useRouter();
    const [title, id] = params || [];
    console.log("params์—์ €์žฅ๋œ๊ฐ’", params);
    return (
        <div>
            <Seo title={title} />
            <h4>{title || "Loading..."}</h4>
        </div>
    );
}
export function getServerSideProps({ params: { params } }) {
    return {
        props: {
            params,
        },
    };
}
</script>

๊ทธ๋Ÿฌ๋ฉด ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด params๊ฐ’์„ ์™ ๋นผ๋‚ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

getSeverSideProps ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๊ทธ ๊ฐ์ฒด ๋ชจ์–‘ ๊ทธ๋Œ€๋กœ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฆฌํ„ด์€ {params}๋ฅผ props๋กœ ํ•œ๋‹ค.

ํ•ด๋‹น url์ฃผ์†Œ๊ฐ€ ํ™œ์„ฑํ™”๋˜๋Š” ํ•จ์ˆ˜์ธ Detailํ•จ์ˆ˜๊ฐ€ {params}๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„๋“ค์—ฌ์„œ ๊ทธ์•ˆ์˜ ๋‚ด์šฉ์„ ์›ํ•˜๋Š” ๋ณ€์ˆ˜์— ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ€ ๋งˆ๋ฌด๋ฆฌ

pages์— movies ํด๋” ๋ฐ‘์— [...parms].js๋ผ๋Š” ํŒŒ์ผ์„ ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„, next.js์„œ๋ฒ„๋Š” { params: { params: [ , ] } } ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ (http://localhost:3000/movies/#####/****)/?? ํ˜•์‹์˜ url ์ฃผ์†Œ๋กœ ์ด๋™ํ•˜๊ฒŒ ๋˜๋ฉด
์„œ๋ฒ„์— { params: { params: [ #### , *** , ?? ] } } ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์ด๊ฐ์ฒด๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
1. router์„ ์ด์šฉํ•œ ๋ฐฉ๋ฒ•
2. getSeverSideProps()๋ฅผ ์ด์šฉํ•œ ๋ฐฉ๋ฒ•
2๋ฒˆ๋ฐฉ๋ฒ•์€ 13 ์ตœ์‹ ๋ฒ„์ „์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€์•Š๋Š”๋‹ค๊ณ ํ•œ๋‹ค.
๋Œ€์‹  ์ด๊ฑธ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

<script>
export async function getStaticProps({ params }:Params) {
return {
props: { params },
};
}
export async function getStaticPaths() {
return {
paths: [], // ๋™์  ๊ฒฝ๋กœ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋นˆ ๋ฐฐ์—ด๋กœ ์„ค์ •
fallback: 'blocking', // ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋กœ์˜ ์ ‘๊ทผ์€ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ ๋Œ€๊ธฐ
};
}
</script>

์ฐธ๊ณ ์ž๋ฃŒ
๋…ธ๋งˆ๋“œ์ฝ”๋”-Next์‹œ์ž‘ํ•˜๊ธฐ
๋…ธ์…˜์ฐธ๊ณ -nextjs์—์„œ params ๋ฐ router

0๊ฐœ์˜ ๋Œ“๊ธ€