โ๏ธ ๊ธฐ๋ก.
๐ ๋ฒ์ 13์์ Next.js ๊ณต์ ๋ ์ด์์, ์ค์ฒฉ ๋ผ์ฐํ , ๋ก๋ฉ ์ํ, ์ค๋ฅ ์ฒ๋ฆฌ๋ฑ์ ์ง์ํ๋ React Server Components๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ถ๋ ์๋ก์ด App Router๋ฅผ ๋์ .
Subtree: ๋ฃจํธ(์ฒซ ๋ฒ์งธ)์์ ์์ํ์ฌ ์(๋ง์ง๋ง)์์ ๋๋๋ ํธ๋ฆฌ์ ์ผ๋ถ์
๋๋ค.
Root: ๋ฃจํธ ๋ ์ด์์๊ณผ ๊ฐ์ ํธ๋ฆฌ ๋๋ ํ์ ํธ๋ฆฌ์ ์ฒซ ๋ฒ์งธ ๋
ธ๋์
๋๋ค.
Leaf: URL ๊ฒฝ๋ก์ ๋ง์ง๋ง ์ธ๊ทธ๋จผํธ์ ๊ฐ์ด ์์์ด ์๋ ํ์ ํธ๋ฆฌ์ ๋
ธ๋์
๋๋ค.
URL Segment : ์ฌ๋์๋ก ๊ตฌ๋ถ๋ URL ๊ฒฝ๋ก์ ์ผ๋ถ์
๋๋ค.
URL Path : ๋๋ฉ์ธ ๋ค์ ์ค๋ URL์ ์ผ๋ถ(์ธ๊ทธ๋จผํธ๋ก ๊ตฌ์ฑ)
โ
Layout
-๋ฃจํธ ๋ ์ด์์์๋ง ๋ฐ ํ๊ทธ๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค.
๐ ์ค์ฒฉ ๊ฒฝ๋ก์์๋ dashboard ์ธ๊ทธ๋จผํธ์ ๊ตฌ์ฑ ์์๊ฐ ์์ ์ธ๊ทธ๋จผํธ ๊ตฌ์ฑ ์์ ๋ด์ ์ค์ฒฉ
โ EX)
dashboard ํด๋(directory) ๋ด layout.tsx ์์ฑํ์๊ณ
settings ํด๋ ๋ด layout.tsx์ page.tsx๋ฅผ ์์ฑ.
// dashboard layout
export default function DashboardLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<div>
1. Dashboard Layout
<hr />
{children}
</div>
);
}
// setting layout
export default function SettingLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<div>
2. Settings Layout
<hr />
{children}
</div>
);
}
// setting page
export default function Setting(){
return (
<div>
3. Settings Page
</div>
)
}
โ /dashboard/settings
โ๏ธ ์์ ๊ฐ์ด ํ์ธํ ์ ์์ต๋๋ค.โ
/dashboard
โ๏ธ dashboard ํด๋ ๋ด UI๋ฅผ ๋ ๋๋งํ๋ page ํ์ผ์ด ์๊ธฐ์ 404 ์๋ฌ๊ฐ ๋์ค๊ณ ์์ต๋๋ค.
โ๏ธ ์๋ฌ ํ๋ฉด์ error.js๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
โ๏ธ ๊ฒฝ๋ก๋ก ์ง์ ์ ํ๊ธฐ ์ํด์ page ํ์ผ์ด ํ์ํฉ๋๋ค.
โ๏ธ .js, .jsx, tsx ํ์ฅ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๐ ๋์ ๋ฐ์ดํฐ์ ๋ฐ๋ผ ๊ฒฝ๋ก๋ฅผ ์์ฑํ๋ ค๋ ๊ฒฝ์ฐ
โ EX)
โ ์ ์์ ์ผ๋ก [id]/page.tsx๊ฐ ๋ณด์ฌ์ง๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
http://localhost:3000/dashboard/settings/5?velog=NEXTJS
// ๐ dashboard/settings/[id]/page.tsx
export default function SettingId(props) {
console.log(props)
return (
<div>
Page
</div>
)
}
โป console.log ์๋ฒ ์ปดํฌ๋ํธ ํฐ๋ฏธ๋์์ ํ์ธ ๊ฐ๋ฅ
โ 'use client' : ํด๋ผ์ด์ธํธ์ผ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ์ฝ์์์ ํ์ธ ๊ฐ๋ฅ.
export default function SettingId({
params
} : {
params : { id : string},
}) {
return (
<div>
{params.id} Page
</div>
)
}
โ params id ๊ฐ ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
โ [ํด๋์ด๋ฆ] ๋ณ๊ฒฝํด์ ์ฌ์ฉ ๊ฐ๋ฅ๐ Route Group์ URL ๊ฒฝ๋ก์ ์ํฅ์ ๋ฏธ์น์ง ์๋๋ค.
โ
/account -> ๋ฃจํธ layout.js์ (shop) layout.js ํฌํจ account page
โ
checkout -> ๋ฃจํธ layout.js๋ง ํฌํจํ page
๐ ์ปดํฌ๋ํธ(component)
โ
Next.js์์๋ ์๋ฒ์์ server component, client component ๋ชจ๋ ํ์ด์ง per-render ๋๋ค.
: ์ด๊ธฐ ํ๋ฉด์ ๋น ๊ฐ์ด ์๋ ๋ง๋ค์ด์ง ํ๋ฉด์ ๋ณผ ์ ์๋ค.
๐Next.js์์๋ React 18 ์ถ์ ํ ๋์ ๋ ๊ธฐ์ RSC(React Server Component) / RCC(React Client Component) ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
โ ๊ณต์๋ฌธ์ RSC์ RCC์ ์ญํ ์ด ๊ตฌ๋ถ๋์ด ์๊ธฐ์ ์ํฉ์ ๋ง๊ฒ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด์ผํฉ๋๋ค.
๐ App directory ๋ด๋ถ์ ์ปดํฌ๋ํธ ์์ฑ์ ๊ธฐ๋ณธ์ผ๋ก ์๋ฒ์ปดํฌ๋ํธ๊ฐ ๋๋ฉฐ, ๋ณ๋ ์ง์ ์ด ํ์ ์์ต๋๋ค. (๊ธฐ๋ณธ ํ์ผ server component)
export default function ServerComponent() {
return (
<div>
<p>Server Component</p>
</div>
);
}
โ Server Component
๐ ์๋ฒ์์ ๊ธฐ๋ณธ html ๋ ๋๋ง ํ Hydrate ๊ณผ์ ์ ๊ฑฐ์ณ React hook, Event Listener๋ฅผ ์ถ๊ฐํ์ฌ ๋ง๋ค์ด์ง๋ค.
'use client' // ๐ client component
import { useState } from 'react'
export default function Counter() {
const [state, setState] = useState(0) // React hook
return (
<div>
<p>{state}</p>
<button onClick={() => setState(state + 1)}>
Click Event Listener
</button>
</div>
)
}
โ 'use client' Client Component ๋ง๋ค๊ธฐ
// Client Component
'use client'
export default function ClientComponent({
children, // Server component ์์ ์์๋ก ์ ๋ฌ.
} : {
children: React.ReactNode
}) {
return (
<div>
<p>Client Component</p>
<button onClick={()=>console.log("Client component")}>๋ฒํผ</button>
<p>๐ Server Component</p>
{children}
</div>
);
}
// Parent Component
// ๐ Client Component children์ผ๋ก ์ ๋ฌ
...
<ClientComponent>
<ServerComponent />
</ClientComponent>
...
โ Client Component์์ Server Component props๋ก ์ฌ์ฉ.
๐
Nextjs org
RSC,RCC ์ฐธ๊ณ