๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š ์‹œ๋ฆฌ์ฆˆ/- ์ •์งํ•˜๊ฒŒ ๋ฐฐ์›Œ๋ณด๋Š” Next js

[์ •์งํ•˜๊ฒŒ ๋ฐฐ์›Œ๋ณด๋Š” Next js] ํŽ˜์ด์ง€๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ Link-Component๊ทธ๋ฆฌ๊ณ  Pre-Fetch

by Wonit 2020. 12. 29.

ํ•ด๋‹น ๋ธ”๋กœ๊ทธ ์‹œ๋ฆฌ์ฆˆ๋Š” ์ •์งํ•˜๊ฒŒ ๋ฐฐ์›Œ๋ณด๋Š” Next js ์‹œ๋ฆฌ์ฆˆ๋กœ์จ ์ด 8๋ถ€์ž‘์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
Next.js๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ด์•ผ๊ธฐํ•˜๋Š” ๋‚ด์šฉ์„ ์ตœ๋Œ€ํ•œ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์ง๊ด€์ ์ด๊ฒŒ ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

0. ๋ชฉ์ฐจ

1. create-next-app์œผ๋กœ next ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ธํŒ…ํ•˜๊ธฐ

2. create-next-app์—์„œ ๋งŒ๋‚œ ์ฒซ ๋ฒˆ์งธ ํ•ต์‹ฌ pages. ๊ทธ๋ฆฌ๊ณ  ๋™์  ๋ผ์šฐํŒ…

3. ํŽ˜์ด์ง€๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ Link-Component ๊ทธ๋ฆฌ๊ณ  Pre-Fetch

Dynamic Routing๊ณผ Link๋ฅผ ์ด์šฉํ•ด ๊ฐ„๋‹จํ•œ ๊ฒŒ์‹œํŒ์„ ๋งŒ๋“ค์–ด๋ณด์ž.

4. Next.js์—์„œ head ํƒœ๊ทธ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ฉ‹์ง„ ๋ฐฉ๋ฒ•

๋ฒˆ์™ธ & ์‹ค์Šต) ์ด๋ฏธ์ง€์™€ ๋™์˜์ƒ์„ ์ €์žฅํ•˜๊ณ  ์‚ฌ์šฉํ•ด๋ณด์ž.

5. ์›น์˜ ๋ฐœ์ „ ๊ณผ์ •์œผ๋กœ ๋ณด๋Š” SSG์™€ SSR

6. next์˜ ๋‘ ๋ฒˆ์งธ ํ•ต์‹ฌ Pre-Rendering

7. SSG๋กœ ๊ฒ€์ƒ‰ ์—”์ง„ ์ตœ์ ํ™” ๋…ธ๋ฆฌ๊ธฐ

8. ์ •์งํ•˜๊ฒŒ ๋ฐฐ์›Œ๋ณด๋Š” Next.js ์‹œ๋ฆฌ์ฆˆ๋ฅผ ๋งˆ์น˜๋ฉฐ..


์šฐ๋ฆฌ๊ฐ€ ํŽ˜์ด์ง€๋ผ๋ฆฌ ์—ฐ๊ฒฐํ•  ๋•Œ ์–ด๋–ค ํƒœ๊ทธ๋ฅผ ์ผ๋Š”์ง€ ์ƒ๊ฐํ•ด๋ณด์ž.

 

์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์—ฐ๊ฒฐ์ด๋ž€? ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฑฐ๋‚˜ ๊ฒŒ์‹œํŒ์—์„œ ๊ธ€์„ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ•˜๋Š” ํ–‰๋™์„ ํ–ˆ์„ ์‹œ์— ์šฐ๋ฆฌ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ณด๊ฒŒ๋˜๋Š” view๋ฅผ ๋ฐ”๊ฟ”๋ณด์ž๋Š” ์ด์•ผ๊ธฐ๋‹ค.

 

์šฐ๋ฆฐ html์˜ <a></a> ๋ฅผ ์ด์šฉํ•ด์„œ ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ–ˆ๋‹ค.

 

๊ทผ๋ฐ ์ด <a></a>ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•  ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ viewport ์ „์ฒด๋ฅผ ์ƒˆ๋กญ๊ฒŒ Renderingํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ™”๋ฉด์ด ๊นœ๋นก๊ฑฐ๋ฆฌ๋ฉฐ ํ•„์š”ํ•˜๋‹ค๋ฉด ๋„คํŠธ์›Œํฌ๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๊ณผ์ • ์ž์ฒด๋ฅผ Next JS ์—์„œ๋Š” Client Side Routing ์œผ๋กœ ํŽ˜์ด์ง€๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ Single Page Application ์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด ๋„คํŠธ์›Œํฌ ๊ฐœ์ž…์„ ์—†์•ค๋‹ค.

 

์•„๋‹ˆ ์ž ๊น ๋ญ”๊ฐ€ ์ด์ƒํ•˜๋‹ค. ์šฐ๋ฆฌ๋Š” SSR์„ ๋ฐฐ์šฐ๋Ÿฌ ์™”๋Š”๋ฐ ์™œ CSR์„ ํ•ด?

 

๋‚˜๋ฅผ ํฌํ•จํ•œ ์‚ฌ๋žŒ๋“ค์ด ์˜คํ•ดํ•˜๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค.


๋‚˜๋Š” SPA์˜ CSR์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ณ ์ž SSR์„ ์œ„ํ•œ Next JS๋กœ ์˜ค๊ฒŒ ๋˜์—ˆ๋‹ค.


๋‚˜์™€ ๋น„์Šทํ•˜๊ฒŒ react์—์„œ next๋กœ ์œ ์ž…๋œ ์‚ฌ๋žŒ๋“ค์ด์ง€๋งŒ ์ด๊ฒƒ ํ•˜๋‚˜๋Š” ํ™•์‹คํžˆ ํ•ด์•ผํ•œ๋‹ค.

 

์šฐ๋ฆฌ๋Š” next.js๋ฅผ Server Side Rendering ์„ ํ•˜๋ ค๊ณ ๋งŒ ์“ฐ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ.

Server Side Rendering์˜ ์žฅ์ ๊ณผ Client Side Rendering ์˜ ์žฅ์ ์„ ์ ์ ˆํžˆ ์„ž์€ ์ข‹์€ ์„ฑ๋Šฅ์˜ ์•ฑ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์—ผ๋‘ํ•ด์•ผ ํ•œ๋‹ค.

 

์–ด๋–ป๊ฒŒ Next js๊ฐ€ Client Side Rendering์„ ์ข‹์€ ์„ฑ๋Šฅ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ์ง€๋Š” ๋‹ค์Œ์— ์žˆ์„ Pre-Rendering์—์„œ ์•Œ์•„๋ณผ ๊ฒƒ์ด๊ณ , ์˜ค๋Š˜์€ ๊ฐ€๋ณ๊ฒŒ Link์™€ Pre-Fetch ์— ๋Œ€ํ•ด์„œ๋งŒ ์•Œ์•„๊ฐ€๋„ ์ถฉ๋ถ„ํ•˜๋‹ค.

Link

์šฐ๋ฆฌ๋Š” ์ง€๋‚œ ์‹œ๊ฐ„ ๋™์  ๋ผ์šฐํŒ…์œผ๋กœ url ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ์˜ค๋Š˜์€ ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์„ ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.


next/link, <Link />๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ Pre-Fetch๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜์ง€ ์•Š๊ณ  ์ด๋™ ํ•  ์ˆ˜ ์žˆ๋‹ค.

import Link from "next/Link";

๋ฅผ ์ด์šฉํ•ด์„œ Link ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ž.

 

๊ทธ๋ฆฌ๊ณ  index.jsx๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”๋ณด์ž.

import Link from 'next/link'

function Home() {
  return (
    <ul>
      <li>
        <Link href="/">
          <a>Home</a>
        </Link>
      </li>
      <li>
        <Link href="/about">
          <a>About Us</a>
        </Link>
      </li>
    </ul>
  )
}

export default Home

๊ทธ๋Ÿฐ ๋‹ค์Œ pages ๋””๋ ‰ํ† ๋ฆฌ์— about.jsx๋ฅผ ๋งŒ๋“ค๊ณ  export ํ•ด๋ณด์ž.

import React from "react";

const About = () => {
  return <div>์ €๋Š” ์˜ค๋Š˜ nextjs ๋ฅผ ์ฒ˜์Œ ๋ฐฐ์›Œ์š”</div>;
};

export default About;

๊ทธ๋Ÿผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด index.jsx์™€ about.jsx๊ฐ€ ์—ฐ๊ฒฐ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋™์  ๋ผ์šฐํŒ…๊ณผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

๋™์  ๋ผ์šฐํŒ…๊ณผ ์—ฐ๊ฒฐํ•œ๋‹ค๊ณ  ํ•ด๋„ ํฌ๊ฒŒ ์–ด๋ ค์šธ ๊ฒƒ์ด ์—†๋‹ค.

 

์šฐ์„  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŒŒ์ผ๊ณผ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  pages ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— index.jsx ํŒŒ์ผ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•ด์ฃผ์ž.

import Link from "next/link";

const users = [
  { id: 1, name: "James" },
  { id: 2, name: "Martin" },
  { id: 3, name: "Danial" },
];

function Home() {
  return (
    <ul>
      <li>
        <Link href="/">
          <a>Home</a>
        </Link>
      </li>
      <li>
        {users.map((user) => (
          <ul key={user.id}>
            <Link href={`/user/${encodeURIComponent(user.id)}`}>
              <a>{user.name}</a>
            </Link>
          </ul>
        ))}
      </li>
    </ul>
  );
}

export default Home;

์—ฌ๊ธฐ์„œ encodedURIComponent()๊ฐ€ ์“ฐ์˜€๋Š”๋ฐ, ํ˜น์‹œ ๋ฌธ์ž์—ด๋กœ url์ด ๋“ค์–ด๊ฐ„๋‹ค๋ฉด utf-8 ํ˜•์‹์„ ์ง€์ผœ์ฃผ๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.
๋จ„์•… ์ˆซ์ž ํ˜•ํƒœ์˜ url path๋ผ๋ฉด ์ƒ๋žตํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  pages ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— user ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  [id].jsx ํŒŒ์ผ์„ ๋งŒ๋“  ๋’ค, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•˜์ž.

import React from "react";
import { useRouter } from "next/router";
const User = () => {
  const router = useRouter();

  const { id } = router.query;

  return <div>{id} ๋ฒˆ user์˜ ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.</div>;
};

export default User;

๊ทธ๋Ÿผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž˜ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Link ์ปดํฌ๋„ŒํŠธ์˜ Props

Link ์ปดํฌ๋„ŒํŠธ๋Š” ํŠน์ • ์†์„ฑ๋งŒ์„ ๋ฐ›๋Š” HOC์ด๊ธฐ ๋•Œ๋ฌธ์— ์ง€์ •๋œ ์†์„ฑ์ด ์•„๋‹ˆ๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฟœ์–ด๋‚ธ๋‹ค.

 

๊ทธ๋ž˜์„œ ์ง€์ •๋œ Attribute๋งŒ props๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์•„๋ž˜๋Š” ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์— ๋‚˜์˜ค๋Š” ์ง€์ •๋œ Props ๋“ค์ด๋‹ค.

 

 

๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ React-router-dom์˜ Link๋กœ ์ฐฉ๊ฐํ•˜๊ณ  className ์†์„ฑ์„ ์ค€๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

 

Warning: Failed prop type: Link: unknown props found: title

์ด๋Ÿฐ ์˜ค๋ฅ˜๋ฅผ ๋ฑ‰์–ด๋‚ธ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋งŒ์•ฝ link์— ๋‹ค๋ฅธ ์†์„ฑ์„ (props)๋ฅผ ๋ฐ›๊ณ ์‹ถ๋‹ค๋ฉด Link๋งŒ ์“ธ๊ฒŒ ์•„๋‹ˆ๋ผ Link ์•ˆ์— a ํƒœ๊ทธ๋ฅผ ๋„ฃ๊ณ  ํ•ด๋‹น ํƒœ๊ทธ์— attribute๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ๋œ๋‹ค.

Code Splitting ๊ณผ Prefetching

Next๊ฐ€ Code Splitting ์„ ์ด์šฉํ•ด์„œ...

์ตœ์ดˆ ํŽ˜์ด์ง€ ์š”์ฒญ์ด ์žˆ๋‹ค๋ฉด ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” Single Page Application๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ Next js ์—์„œ๋Š” ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ๋ถ„ํ• ํ•ด์„œ ํ•ด๋‹น ํŽ˜์ด์ง€์— ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ๋กœ๋“œํ•œ๋‹ค.


์ฆ‰, ํ™ˆํŽ˜์ด์ง€๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Code Splitting์ด ์žˆ๋‹ค๋ฉด ์ˆ˜๋ฐฑ๊ฐœ์˜ ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋”๋ผ๋„ ํŽ˜์ด์ง€๋Š” ๋น ๋ฅด๊ฒŒ ๋กœ๋“œ๋  ์ˆ˜ ์žˆ๋‹ค.

 

Next๊ฐ€ Pre-Fetcing ์„ ์ด์šฉํ•˜๋‹ˆ๊นŒ...

 

๊ทธ๋ฆฌ๊ณ  Next js๋Š” build ์‹œ์ ์— Link ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์— ํ‘œ์‹œ๋  ๋•Œ๋งˆ๋‹ค ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋งํฌ๋œ ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.


๊ทธ๋ž˜์„œ ํŽ˜์ด์ง€์˜ ์ „ํ™˜์ด SPA์™€ ๋น„์Šทํ•˜๊ฒŒ ์ฆ‰์‹œ ์ด๋ฃจ์–ด์ง€๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๋Š๋‚„ ์ˆ˜ ์žˆ๋‹ค.

๋Œ“๊ธ€