React로 만들어진 FrameWork
Next.js로 만든 high-Quality 웹사이트
1. 성능
라우팅을 위한 제어를 미리 해주고 있기 때문에 사용방법에 맞추어 사용하기만 하면 된다.
: Next.js는 폴더구조를 기반으로 한 라우팅
npx create-next-app@latest
ex)
acme.com / dashboard / settings
Domain/segment/segment
Domain/Path
import Link from "next/link";
export default function Home() {
return (
<div>
안녕하세요 Next.js입니다.
<Link href={"/test"}>Test로 이동하기</Link>
</div>
);
}
"use client";
import { useRouter } from "next/navigation";
export default function Test () {
const router = useRouter();
const handleButtonClick = () => {
로직1();
로직2();
...
router.push("/new_location");
}
return <button onClick={handleButtonClick}>클릭!</button>
}
: 브라우저는 history stack을 차곡차곡 쌓아준다.
1. router.push
=> 원하는 스코프에 layout을 적용하기 위해 사용할 수 있다.
const AdminLayout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return (
<>
<h1>admin페이지 입니다.</h1>
{children}
</>
);
};
export default AdminLayout;

Next.js는 기본적으로 제공해준다.
1. 직접 만들고 싶다면 src>app 에서 not-found.tsx 파일을 만들어줌
2. 내부를 커스텀
export const metaData: Metadata = {
title: "안녕하세요 About Page입니다.",
description: "Generated by create next app",
};

page.tsx에서도 각각의 페이지에 맞게끔 똑같이 사용가능
import { Metadata } from "next";
import Link from "next/link";
type Props = {
params: {
id: string;
};
};
export const metaData: Metadata = ({ params }: Props) => {
return {
title: "안녕하세요 About Page입니다.",
description: "Generated by create next app",
};
};
기본 단위인 1이 0.25rem(4px)을 의미
1rem = 16px
useEffect 등 client에서 실행되어야 하는 훅들을 사용할 때는
use client를 꼭 작성해줘야 사용할 수 있다.
use client를 사용하게 되면 dom tree 로 아래에 적혀있는 것들이 모두 적용되게 된다.
"use client"; // 꼭 작성해줘야 함
import { useEffect } from "react";
export default function Home() {
useEffect(() => {}, []);
return <div>안녕하세요 홈입니다.</div>;
}
따라서 page.tsx에는
import ClientExample from "./component/ClientExample";
export default function Home() {
console.log("안녕 난 서버 컴포넌트야");
return (
<div>
안녕하세요 홈입니다.
<ClientExample />
</div>
);
}
내부로직에 있는 ClientExample 컴포넌트에
"use client";
import React, { useEffect } from "react";
const ClientExample = () => {
useEffect(() => {
console.log("안녕, 난 클라이언트 컴포넌트여");
}, []);
return <div>ClientExample</div>;
};
export default ClientExample;
넣어주게 된다면 page.tsx의 console.log는 vscode terminal(server)에서 ClientExample의 console.log는 client에서 실행된다.
Next.js에서는 SPA에서 모든 페이지를 렌더링 해오기전까지 빈화면이 나타나는 현상을 보완하기 위해
// SSG
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
cache: "force-cache",
});
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
cache: "no-store",
});
"use client";
import { useEffect, useState } from "react";
import { Product } from "../page";
const fetchData = async () => {
const res = await fetch("http://localhost:4000/products");
const data: Product[] = await res.json();
return data;
};
const ProductList = () => {
const [data, setData] = useState<Product[]>([]);
useEffect(() => {
console.log("render");
fetchData().then(setData);
}, []);
return (
export default async function Home() {
const res = await fetch("http://localhost:4000/products", {
next: {
revalidate: 3,
},
});
const data: Product[] = await res.json();
src>app에서
loading.tsx생성
export default function Loading() {
return <>Loading...</>;
}
import { Suspense } from "react";
import NewProductList from "./component/newProductList";
import ProductList from "./component/ProductList";
import Loading from "./loading";
export default async function Home() {
return (
<div>
<Suspense fallback={<Loading />}>
<NewProductList />
</Suspense>
<Suspense fallback={<Loading />}>
<ProductList />
</Suspense>
</div>
);
}
"use client";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.error(error);
}, [error]);
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
);
}
☘️ 에러가 클라이언트 컴포넌트여야하는 이유!
class컴포넌트에서 제공하는 라이프 사이클을 사용하기 위해서!
"use client";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}
"use client";
import { useRouter } from "next/router";
import { startTransition, useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
const { refresh } = useRouter();
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={() =>
startTransition(() => {
refresh();
reset();
})
}
>
Try again
</button>
</div>
);
}