devlog study nextjs react app-router fullstack
Next.js ๐
์๋ฌธ๊ฐ๊ธฐ
RootLayout ์์ page.tsx๋ฅผ importํด์ ๋ฃ์ ์ ์ด ์๋๋ฐ ์ด๋ป๊ฒ ๋ ๋๋ง๋์ง?
Next.js App router๋
{children}์๋ฆฌ์ ์๋์ผ๋ก ํ์ route component(page.tsx)๋ฅผ ๋ผ์๋ฃ๋๋ค
app/
โโ layout.tsx (RootLayout)
โโ page.tsx (ํ ํ์ด์ง /)
โโ about/
โโ page.tsx (/about)์ด๋ฐ ๊ตฌ์กฐ์ผ๋
- user๊ฐ
/URL ์์ฒญ โ Next.js๋app/page.tsx๋ฅผ ์ฐพ์์
โapp/layout.tsx์{children}์๋ฆฌ์ ์๋์ผ๋ก ๋ฃ์ - user๊ฐ
/aboutURL ์์ฒญ
โ Next.js๋app/about/page.tsx๋ฅผ ์ฐพ์์
โapp/layout.tsx์{children}์๋ฆฌ์ ๋ฃ์
useSearchParams๋ query string์ ๋น๋๊ธฐ๋ก ๊ฐ์ ธ์ค๋๋ฐ ์ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฐ์ง ์์ง?
useSearchParams๋ ๋๊ธฐ์ ์ธ ๊ฐ!
"use client";
import { useSearchParams } from "next/navigation";
export default function Page() {
const searchParams = useSearchParams();
const search = searchParams.get("q"); // ๊ทธ๋ฅ ๋๊ธฐ์ ์ผ๋ก ์ฌ์ฉ
return <div>๊ฒ์์ด: {search}</div>;
}- ๋ธ๋ผ์ฐ์ ์์
window.location.search๋ฅผ ์ฐ๋ฉด ํ์ฌ URL์ query string์ ๋ฐ๋ก ๊ฐ์ ธ์ด- ๋คํธ์ํฌ ์์ฒญ(fetch)์ด ์๋๋ผ ํ์ฌ ๋ธ๋ผ์ฐ์ ์ฃผ์์ฐฝ์ ๊ฐ์ ๊ฐ์ ธ์ด
- React state์ฒ๋ผ ๋ผ์ฐํธ๊ฐ ๋ฐ๋๋ฉด ์๋์ผ๋ก ๊ฐฑ์ ๋จ
- โdynamically evaluatedโ
- ๋น๋ ์์ ์๋ ์์ ์๊ณ , ์์ฒญ(request) ์์ ์๋ง ์์ ์์
- โdynamically evaluatedโ
์ buildtime error๊ฐ ๋์ <Suspense> ์ปดํฌ๋ํธ๋ก ๊ฐ์ธ์ค์ผํ๋๊ฑธ๊น?
useSearchParams๋ reactive state๋ผ์ ๋ด๋ถ์ ์ผ๋ก Suspense-ready๋ก ๊ฐ์ธ๊ณ ์๋ค โ runtime์์ ์ค๋น๋ ๋๊น์ง Suspense fallback์ ๊ทธ๋ ค์ค์ผํจ
useSearchParmas๋ Client component!- build time์๋ ์กด์ฌํ์ง ์๋ ๊ฐ
- ๊ฐ์ด ์ค๋น๋๊ธฐ ์ ์๋ pending ์ํ๋ก ๋ (React Suspense ๊ธฐ๋ฐ โlazyโ ๊ฐ)
- ์ด ๋๋ฌธ์
<Suspense>๋ก ๊ฐ์ธ์ค์ผํจ
- ์ด ๋๋ฌธ์
์ React ๋์ ์ Next.js๋ฅผ ์ฐ๋๊ฑธ๊น?
Next.js๋ React์ ๋จ์ ์ธ ์ด๊ธฐ ๋ก๋ฉ ์๋์ SEO ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ , SSRยทSSGยทISR ๊ฐ์ ๋ค์ํ ๋ ๋๋ง ๋ฐฉ์์ ์ ๊ณตํด์ ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ๊ณผ SEO ๊ฒ์๋ ธ์ถ์ ๋ณด์ฅํ๋ค
CSR(Client Side Rendering) - React
- ์ด๊ธฐ์๋ ๋น HTML + JS๋ง ๋ด๋ ค์์ ๋ธ๋ผ์ฐ์ ๊ฐ ์คํํ๋๋ฐ ์๊ฐ์ด ํ์ : ์ฒซ ๋ก๋ฉ ์๋ ๋๋ฆผ
- ํฌ๋กค๋ฌ๋ JS ์คํ ์ ์ด๋ผ ์ฝํ ์ธ ๋ฅผ ์ฝ์ง ๋ชปํด์ SEO ๋ถ๋ฆฌ
Next.js
-
React์ ์ํ๊ณ๋ฅผ ๊ทธ๋๋ก ์ฐ๋ฉด์๋ ๋ผ์ฐํ , API Routes ๋ฑ ํ์คํ ๊ธฐ๋ฅ ์ ๊ณต
-
SSR (Server-Side Rendering): ์๋ฒ์์ ์์ฑ๋ HTML์ ๋ด๋ ค์ฃผ๊ธฐ ๋๋ฌธ์ ์ด๊ธฐ ์๋ ๋น ๋ฅด๊ณ SEO ์นํ์
-
SSG (Static Site Generation): ๋น๋์ HTML ์์ฑ โ ์๋ ๋งค์ฐ ๋น ๋ฅด๊ณ ํธ๋ํฝ์ ๊ฐํจ
-
ISR (Incremental Static Regeneration): static ํ์ด์ง๋ ์ผ์ ์ฃผ๊ธฐ๋ง๋ค ๊ฐฑ์ ๊ฐ๋ฅ โ ์ต์ ์ฑ + ์ฑ๋ฅ ๋ชจ๋ ๊ฐ์ถค
-
๋ฉด์ ์ง๋ฌธ์ผ๋ก ์์ฃผ ๋์ด
- ํด๋น ํ์ฌ ์๋น์ค ๋ถ์ํด์ ์ด๋ ํ์ด์ง๋ฅผ ์ด๋ค ๋ ๋๋ง ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ฉด ์ข์์ง ํจ๊ป ๋ง๋ถ์ฌ ๋๋ตํ๋ฉด ์ข์ ๋๋ต์ผ๋ก ๋ง๋ค์ ์์!
๋ด์ด๋ณด๊ธฐ
-
dynamic page์์ ๋น๋๊ธฐ๋ก ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ์๋ static page๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ ์์
- app-router ์
generateStaticParams: ์ด๋ค ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋์ง ์ํ๋ก ๋ง๋ค์ด๋- ์ฌ๊ธฐ์์ ๋ฆฌํดํ๋ ๊ฐ์ฒด์ ๊ฐ์ โstringโ๋ง ๊ฐ๋ฅํจ
- page-router์
getStaticPath์ ๋์ผํ ๊ธฐ๋ฅ
- app-router ์
-
hidden input tag์๋
readOnlyattribute tag๋ฅผ ์ค์ ํด์ค์ผํจ -
divorformํ๊ทธ๋ก ๋ฒํผ ๊ธฐ๋ฅ์ ๋ง๋ค๊ณ ์ถ์ผ๋ฉด โuseRef์ฌ์ฉ!
streaming
- ํฐ ๋ฐ์ดํฐ๋ฅผ ์๊ฒ ์ชผ๊ฐ์ ์ฐ์์ ์ผ๋ก ๋ณด๋ด๋ ๊ธฐ์
- ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ๋ฐ์ง ์์ ์ํ์์ ํ๋ฉด์ ๋๊น์์ด ๋ณผ์ ์์
- async - ๋๋ฆฌ๊ฒ ๋ ๋๋ง ๋๋ ๋ถ๋ถ : ๋์ฒด UI(๋ก๋ฉ๋ฐ)๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ
- dynamic page์์ ํ์ฉ
- cf. Static page๋ full route cache์ ์ ์ฅ๋จ
- UX : user experience๊ฐ ์ค์ํจ!!
Page streaming
- ๋์ผ ๋ผ์ฐํฐ์ ์๋ page์ ๋ํ ์คํธ๋ฆฌ๋ฐ์ ๋์ฒด UI(loading)๋ฅผ ์ค์ ํ๋ ค๋ฉด
loading.tsx์์ฑ - ์ฃผ์์ฌํญ
- component์ ๋ํด์๋ ์ค์ X
- query string ๊ฐ์ ๋ณํ์ ๋ํด์๋ page์ด๋์ด ์๋๊ธฐ๋๋ฌธ์ ์ค์ ํ ์ ์์
- ๋น๋๊ธฐ-dynamic page์ ๋ํด์๋ง ์ ์ฉ๋จ
Component streaming
Suspenseํ์ฉ- Skeleton UI : ๋ผ๋๋ง ๋ณด์ฌ์ฃผ๋ UI
Server Actionsโจโจโจ
Parallel route & Intercepting route
- @ : slot
- (.)ํด๋๋ช
: route group
- ์ธํฐ์ ํ ํ ํ์ด์ง๋ฅผ ๊ฐ๊ณ ์๋ ํด๋
- intercepting route๋ CSR๋ฐฉ์์ผ๋ก ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๊ฒฝ์ฐ(navigation or )์ผ๋๋ง ๊ฐ๋ฅ
- modal ํ์ด์ง๋ก ๋์
- ํน์ ํ์ด์ง๋ฅผ interceptํด์ Modal๋ก ๋์ฐ๊ณ ๋ฐฐ๊ฒฝ์ parallel route๋ฅผ ํ์ฉํด ๊ธฐ์กด์ ํ์ด์ง๋ฅผ ๋์ฐ๋ฉด ์์ฐ์ค๋ฌ์ด UI๋ฅผ ๋ง๋ค์ ์์
Component Props
- ํน์ ์ปดํฌ๋ํธ์ prop๋ค์ ํค๋ก ๋ฐ์์ ๊ทธ ์์ฒด๋ฅผ ์ฌ์ฉ?
Auth.js
Runtime
์ฐธ๊ณ ํ๊ธฐ
์ฐพ์๋ณด๊ธฐ
- GET/POST ๊ธฐ๋ณธ ๊ฐ๋
- WS / WAS
- Edge : auth ํจ์
- Node : signIn, signOut ํจ์