TIL/Next.js

Next.js ๊ธฐ์ดˆ 1 - ์‹œ์ž‘ํ•˜๊ธฐ & ๋ผ์šฐํŒ… & ์ด๋ฏธ์ง€ ๋„ฃ๊ธฐ

fairy_taIe 2023. 5. 20. 21:33

์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์›Œํฌ next.js๋ฅผ ๋ฐฐ์›Œ๋ณด๋ ค๊ณ  ํ•œ๋‹ค.
์™œ? client-side rendering ๋ง๊ณ  server-side rendering๊ฐ€ ์œ ํ–‰ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ .

client-side rendering : ๋ธŒ๋ผ์šฐ์ €์—์„œ html์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋งŒ๋“ฆ
server-side rendering : ์„œ๋ฒ„์—์„œ html์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋ณด๋‚ด ์คŒ

client-side rendering์€ ๊ฒ€์ƒ‰์—๋„ ์ž˜ ๋…ธ์ถœ๋˜์ง€ ์•Š๊ณ , ํŽ˜์ด์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐ์— ์‹œ๊ฐ„์ด ์ œ๋ฒ• ๊ฑธ๋ ค์„œ ๋ˆ์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ํŽธ์ด๋ผ ํ•œ๋‹ค
๊ทธ๋ž˜์„œ server-side rendering ์œผ๋กœ ๊ฐˆ์•„ํƒ€๋Š” ์ถ”์„ธ๋ผ๊ณ  ํ•˜๋‹ˆ ์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ•ด๋ณด์Ÿˆ



ํ™˜๊ฒฝ ์„ธํŒ…๐Ÿช›

npx create-next-app@latest --experimental-app

์›ํ•˜๋Š” ํด๋”์—์„œ ์œ„๋ฅผ ๋ณต์‚ฌํ•ด ์‹คํ–‰์‹œ์ผœ์ฃผ๋ฉด ๋œ๋‹ค..
๋ฌผ์–ด๋ณด๋Š” ๊ฒƒ๋„ ์ฐธ๋ง ๋งŽ๋‹ค

ํƒญ์ด๋‚˜ ๋ฐฉํ–ฅํ‚ค ์ด์šฉํ•ด์„œ ์—”ํ„ฐ~ ๋ˆŒ๋Ÿฌ์ฃผ๋ฉด์„œ ์„ ํƒํ•ด์ฃผ๋ฉด ๋จ.
๋งŒ๋“  ํด๋”๋กœ ๋“ค์–ด๊ฐ€์„œ npm install ๋„ ํ•ด์ค€๋‹ค.
page.js๊ฐ€ ๋ฉ”์ธ ํŽ˜์ด์ง€๊ณ 

npm run dev

๋กœ ์‹คํ–‰์‹œ์ผœ ๋ฐ”๋กœ๋ฐ”๋กœ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค


์–ด์ฐจํ”ผ ๋น„์šธ ๊ฑฐ์ง€๋งŒ ๊ฐ„์ง€๋‚˜๋Š”๊ตฌ๋งŒ..


๊ทธ๋ฆฌ๊ณ  ์™„์ „ ๊ทน ์ตœ์‹ ๋ฒ„์ „์€ ์—๋Ÿฌ๊ฐ€ ๋งŽ์ด ๋‚  ์ˆ˜ ์žˆ์œผ๋‹ˆ package.json์—์„œ ์กฐ๊ธˆ ๋‹ค์šด์‹œ์ผœ์ค€๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€ ํ•˜๋ฉด ์„ธํŒ…์€ ๋!




๋ผ์šฐํŒ… ๐Ÿ–‡

๊ธฐ์ดˆ ์„ธํŒ…

๋ฆฌ์•กํŠธ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์„ ์ด์šฉํ•ด ์ฒซ ํŽ˜์ด์ง€๋ฅผ ์ผ๋‹จ ์„ธํŒ…ํ•œ๋‹ค.



์ž๋™ ๋ผ์šฐํŒ… ๐Ÿงฒ

next.js ๋Š” ๋ฆฌ์•กํŠธ์—์„œ ์“ฐ๋“ฏ์ด
๋ญ ํ•˜๋ฉด ์ด๊ฑฐ ์ž๋™์œผ๋กœ ๋งํฌ ๋งŒ๋“ค์–ด์ค˜๋ผ~ ํ•˜๊ณ  ์„ธํŒ…ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

์ด๋ ‡๊ฒŒ๋งŒ ์„ธํŒ…ํ•ด์ฃผ๋ฉด ์•Œ์•„์„œ /list ๋ฅผ ์ž…๋ ฅํ–ˆ์„์‹œ ์ € ํŽ˜์ด์ง€๋ฅผ ์ฐพ์•„๊ฐ„๋‹ค.

๋ผ์šฐํŠธ ๊ตฌ์„ฑ

์ผ๋ฐ˜์ ์ธ ๋ผ์šฐํŠธ

  • pages/book.js -> /book
  • pages/book/index.js -> /book
  • pages/index.js -> /

์ค‘์ฒฉ ๋ผ์šฐํŠธ

  • pages/book/essay/index.js -> /book/essay
  • pages/book/novel/like.js -> /book/novel/like
  • pages/book/novel.js -> /book/novel

๋™์  ๋ผ์šฐํŠธ

  • pages/book/[genre]/index.js -> /book/:genre
  • pages/book/[genre]/all.js -> /book/:genre/all
  • pages/book/[...id].js -> /book/* (book/1/like/10)
  • pages/book/[id].js -> /book/:id



๋งํฌ ์‚ฌ์šฉํ•˜๊ธฐ

import Link from "next/link";

	...

<Link href="/">HOME</Link>
<Link href="/list">LIST</Link>

์ƒ๋‹จ๋ฐ” (layout.js)

<div className="navbar">
  	<Link href="/">HOME</Link>
	<Link href="/list">LIST</Link>
</div>

๋ผ๋Š” ๋Œ€๋žต์˜ ์ƒ๋‹จ๋ฐ”๋ฅผ page.js์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.
๊ทผ๋ฐ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋„ˆ๋ฌด๋„ ๋‹น์—ฐํžˆ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„  ์ƒ๋‹จ๋ฐ”๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค.
์ด ๋ถ€๋ถ„์„ ์ผ์ผ์ด ๋ณต๋ถ™ํ•ด์ฃผ๋ฉด ๋˜๊ฒ ์ง€๋งŒ,, ๋งŒ์•ฝ ํŽ˜์ด์ง€๊ฐ€ 10๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ„๋‹ค๋ฉด ๋ญํ•˜๋Ÿฌ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋‚˜!

layout.js

์ด๋Ÿด ๋•Œ ์ด์šฉํ•ด์ฃผ๋Š” ๊ฒƒ์ด layout.js ์ด๋‹ค.

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <div className="navbar">
          <Link href="/">HOME</Link>
          <Link href="/list">LIST</Link>
        </div>
        {children}
      </body>
    </html>
  );
}

๊ฐ„๋‹จํžˆ body ์‚ฌ์ด์— ๋„ฃ์–ด์ฃผ๋ฉด, ์–ด๋А ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•˜๋“  ์ƒ๋‹จ์— ๊ณ ์ •๋˜๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
component๋กœ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๋˜ ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ ์‰ฌ์šด ๋А๋‚Œ??

 

 

์ด๋ฏธ์ง€ ์‚ฝ์ž… ๐Ÿž

<Image />

๋””๋ ‰ํ† ๋ฆฌ ์‚ฌ์ง„

import Image from 'next/image'

export default function Home() {
  return(
    <div>
      <Image />
    <div/>
)} 

๋ฌผ๋ก  ๋ฆฌ์•กํŠธ์—์„œ ์“ฐ๋“ฏ <img src~~/> ์จ๋„ ๋œ๋‹ค.
public ํด๋” ์•ˆ์— ์žˆ๋Š” ์‚ฌ์ง„์„ ์“ฐ๋ ค๋ฉด /๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฉด ๋จ.
๊ทผ๋ฐ ์„ฑ๋Šฅ๊ณผ ์†๋„๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๋ฉด ์ด๋ฏธ์ง€ ๋„ฃ์„ ๋•Œ ํƒœ๊ทธ ์”€.
๊ทธ๋Ÿผ ์ž๋™์œผ๋กœ ์ด๋ฏธ์ง€ lazy loading & ์‚ฌ์ด์ฆˆ ์ตœ์ ํ™” & layout shift ๋ฐฉ์ง€๋ฅผ ํ•ด์ค€๋‹ค.

์ฐธ๊ณ  : https://scarlett-dev.gitbook.io/all/it/lazy-loading
          https://sangwonny.tistory.com/57



import Image from 'next/image'
import ์ด๋ฏธ์ง€ from './food0.png'

export default function Home() {
  return(
    <div>
      <Image src={์ด๋ฏธ์ง€} alt="์„ค๋ช…"/>
    <div/>
)} 

์ด๋ฏธ์ง€๋ฅผ ์ƒ๋‹จ์—์„œ import ํ•ด์˜จ ๋’ค์— ๊ทธ๊ฑธ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.
์‚ฌ์ด์ฆˆ๋‚˜ ์Šคํƒ€์ผ์„ ์กฐ์ •ํ•˜๋ ค๋ฉด ์•Œ๋‹ค์‹œํ”ผ<Image /> ๋‚ด ์—์„œ width="100px" ์š”๋Ÿฐ ์‹์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋จ

 

 

 

 

์™ธ๋ถ€๋งํฌ์‚ฌ์ง„

import Image from 'next/image'

export default function Home() {
  return(
    <div>
      <Image src="https://s3.amazonaws.com/my-bucket/profile.png" width="500" height="500"/>
    </div>
)} 

๋‚ด๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์— ์˜ฌ๋ ค๋†“์€ ์‚ฌ์ง„์„ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด

  • width, height ์˜ต์…˜์„ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•จ
  • fill="true" ์ด๊ฑฐ ๋Œ€์‹  ๋„ฃ๊ณ  ๋ถ€๋ชจ <div>๊ฐ€ width, height๋ฅผ ๋Œ€์‹  ์กฐ์ ˆํ•ด๋„ ๋จ๋‚ด ์ €์žฅ์†Œ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ URL์—์„œ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์œผ๋ฉด ๋”ฐ๋กœ ์…‹ํŒ…๋„ ํ•ด๋†”์•ผํ•ฉ๋‹ˆ๋‹ค.
    https://beta.nextjs.org/docs/optimizing/images#remote-images

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ,

<div>
   <Image src="https://cdn.pixabay.com/photo/2021/10/14/03/19/tomato-6707992__340.png"
          width="500"
          height="500"
   		/>
</div>

์ด๋Ÿฐ pixbay์— ์žˆ๋Š” ์‚ฌ์ง„ ํ•˜๋‚˜๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋ ค๋ฉด, ์ด๋ ‡๊ฒŒ๋งŒ ์ ์œผ๋ฉด ์•ˆ๋œ๋‹ค.
์ •์ ํŒŒ์ผ์˜ ์ ‘๊ทผ์€ ์ƒ๊ด€์—†์ง€๋งŒ ๋‚˜๋Š” ์™ธ๋ถ€ ์„œ๋ฒ„์˜ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋„๋ฉ”์ธ ์„ค์ •์ด ํ•„์š”ํ•จ

Error: Invalid src prop (https://cdn.pixabay.com/photo/2021/10/14/03/19/tomato-6707992__340.png) on next/image, hostname "cdn.pixabay.com" is not configured under images in your next.config.js
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host

๊ท€์ฐฎ์œผ๋‹ˆ ์™ธ๋ถ€ ์‚ฌ์ดํŠธ ์ด๋ฏธ์ง€๋“ค์€ ๊ทธ๋ƒฅ <Image>๋ง๊ณ  <img> ํƒœ๊ทธ ์“ฐ๋Š”๊ฒŒ ํŽธํ•จ

 


 

 

๊ฐ„๋‹จํ•œ map

 

{grocery.map((a, i) => {
  	return (
    		<div className="food" key={i}>
             	<img src={"food" + i + ".png"} width={50} />
  			 	{a} $40
			</div>
			);
	})}

๋‹น์—ฐํžˆ ๋ฐฑํ‹ฑ์„ ์ด์šฉํ•ด๋„ ๋œ๋‹ค (`food{i}.png`)

๊ฐ„๋‹จํ•œ map ์˜ˆ์‹œ!






์—ฌ๋‹ด ๐Ÿ’ฌ


์—๋Ÿฌ๋ฅผ ๋„ฃ์–ด๋ดค๋Š”๋ฐ ์—๋Ÿฌํ‘œ์‹œ๋„ ๊ท€์—ฝ๊ฒŒ ๋‚œ๋‹ค... ใ…‹_ใ…‹
์ด์ œ ์•ˆ ๊ท€์—ฝ๊ฒ ์ง€?