// React 설치 명령어
npx create-react-app
npm run start
// Next 설치 명령어
npx create-next-app@latest . // . 을 쓰면 해당 폴더에 설치를 하겠다는 의미 (이중 폴더가 안생김)
npm run dev
참고 문헌
: Client인 브라우저에서 JS를 로딩 후 그려냄 (렌더링을 함) ex. React, Vite + React

: 서버에서 렌더링된 HTML을 생성하여 클라이언트에 전달하는 방식 ex. Next.js
SSR은 초기 요청 시에 서버 측에서 렌더링된 HTML을 생성하여 클라이언트에 전달하는 방식

+) 내가 ㅂㅋ에서 사용하는 방식은 page router


: 라우트 경로에 특정 값을 넣어 해당하는 페이지로 이동할 수 있게 하는 것 (= path에 어떤 값이 올지 모르는 것!!)

next.js에서는 크게 2가지 방식으로 페이지 이동을 구현할 수 있음.
// 1. next/link의 Link 컴포넌트를 이용
<Link href="/home">HOME</Link>
// 2. router.push() 를 이용
<button onClick={() => router.push("/home")}>HOME</button>
// 3. a 태그를 이용 (이 방식은 next.js 13부터 Link에 지원을 해줘서 불필요)
<a href="/home">HOME</a>
// 구현 코드
<Link href="/home">HOME</Link>
// 빌드 결과
<a href="/home">HOME</a>


npx json-server --port 9999 --watch db.json
// 최신 버전 기준 아래와 같이 입력 필요
npx json-server@0.17.4 --port 9999 --watch db.json


fetch("http://localhost:9999/topics")
.then((resp) => {
return resp.json(); // json으로 받아온 응답을 js로 변환
})
.then((result) => {
return console.log("result : ", result); // 결과값을 출력
});


∴ 단순 정보 부분은 Server Component, 사용자와의 상호작용이 있는 부분은 Client Component로 구현하는 것이 유리
"use client";
import { Topic } from "@/type/topic";
// import type { Metadata } from "next";
import "./globals.css";
import Link from "next/link";
import { useEffect, useState } from "react";
// export const metadata: Metadata = {
// title: "Web tutorial",
// description: "Generated by jisoo",
// };
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const [topics, setTopics] = useState<Topic[]>([]);
useEffect(() => {
fetch("http://localhost:9999/topics")
.then((res) => {
return res.json();
})
.then((result) => {
return setTopics(result);
});
}, []);
return (
<html>
<body>
<h1>
<Link href="/">Web</Link>
</h1>
<ol>
{topics.map((item) => (
<li key={item.id}>
<Link href="/read/2">{item.title}</Link>
</li>
))}
</ol>
{children}
</body>
</html>
);
}
import { Topic } from "@/type/topic";
import type { Metadata } from "next";
import "./globals.css";
import Link from "next/link";
export const metadata: Metadata = {
title: "Web tutorial",
description: "Generated by jisoo",
};
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const resp = await fetch("http://localhost:9999/topics");
const topics = await resp.json();
return (
<html>
<body>
<h1>
<Link href="/">Web</Link>
</h1>
<ol>
{topics.map((item: Topic) => (
<li key={item.id}>
<Link href="/read/2">{item.title}</Link>
</li>
))}
</ol>
{children}
</body>
</html>
);
}
function을 async로 선언
기존 fetch도 비동기적이 아니라, 동기적으로 변경
∴ 서버 쪽에서 fetch 매소드 호출 && topics 데이터까지 가져와서 화면까지 구성 다하고, .next 폴더내에 결과를 저장하고,최종적인 정적인 내용만 client에 전달!!!!

‼️ In previous versions of Next.js, using fetch would have a default cache value of force-cache. This changed in version 15, to a default of cache: no-store.
원래 default가 캐싱이 되는건데, Next.js 15 부터 default가 캐싱 안시키는 걸로 변경됨
// 방법 1 : force-cache
const res = await fetch(`https://api.vercel.app/blog/${id}`, {
cache: 'force-cache', // 강제로 캐시 부여하겠다.
})
const post: Post = await res.json()
if (!post) notFound()
return post
}
// 방법 2 : revalidating
const resp = await fetch("http://localhost:9999/topics", {
next: { revalidate: 0 }, // 0초간 caching을 유지하겠다
});
const topics = await resp.json();
useParams 는 Client Component

위 코드에서 현재 선택된 부분에서 Update와 Delete 버튼을 '/topics/[id]' 일때만 보여지게 하고 싶어
NEXT_PUBLIC_API_URL=http://localhost:9999
const onDeleteClick = () => {
const options = {
method: "DELETE",
headers: { "Content-Type": "application/json" },
};
fetch(`${process.env.NEXT_PUBLIC_API_URL}/topics/${id}`, options)
.then((response) => {
return response.json();
})
.then((result) => {
console.log("result", result);
router.push("/");
router.refresh();
});
};