1. ๋ชฉํ
/blog
: ๊ธ ๋ชฉ๋ก ํ์ด์ง/blog/[id]
: ๊ธ ์์ธ ํ์ด์ง- SCSS ๋ชจ๋๋ก ์คํ์ผ๋ง
- ๋ฐฐํฌ ํ ์ค์ ๋ธ๋ก๊ทธ์ฒ๋ผ ์ ๊ทผ ๊ฐ๋ฅ
๋ฐ์ดํฐ๋ ์ค์ต์ด๋ฏ๋ก JSONPlaceholder API(https://jsonplaceholder.typicode.com/posts)๋ฅผ ์ฌ์ฉํฉ๋๋ค.
2. ๋ธ๋ก๊ทธ ๋ชฉ๋ก ํ์ด์ง
src/app/blog/page.tsx
import Link from "next/link";
import styles from "../../styles/blog.module.scss";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
export default async function BlogPage() {
const res = await fetch("https://jsonplaceholder.typicode.com/posts", {
cache: "no-store",
});
const posts: Post[] = await res.json();
return (
<section className={styles.blogList}>
<h1>๋ธ๋ก๊ทธ ๊ธ ๋ชฉ๋ก</h1>
<ul>
{posts.slice(0, 10).map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>
<h2>{post.title}</h2>
<p>{post.body.slice(0, 80)}...</p>
</Link>
</li>
))}
</ul>
</section>
);
}
3. ๋ธ๋ก๊ทธ ์์ธ ํ์ด์ง
src/app/blog/[id]/page.tsx
import styles from "../../../styles/blog.module.scss";
type Post = {
userId: number;
id: number;
title: string;
body: string;
};
export default async function BlogDetailPage({
params,
}: {
params: { id: string };
}) {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts/${params.id}`,
{ cache: "no-store" }
);
if (!res.ok) {
return <p>ํด๋น ๊ธ์ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.</p>;
}
const post: Post = await res.json();
return (
<article className={styles.blogDetail}>
<h1>{post.title}</h1>
<p>{post.body}</p>
</article>
);
}
4. ์คํ์ผ๋ง (SCSS)
src/styles/blog.module.scss
.blogList {
max-width: 720px;
margin: 2rem auto;
padding: 1rem;
h1 {
font-size: 2rem;
margin-bottom: 1.5rem;
}
ul {
list-style: none;
padding: 0;
display: grid;
gap: 1.2rem;
}
li {
border: 1px solid #eee;
border-radius: 12px;
padding: 1rem;
background: #fff;
transition: box-shadow 0.2s;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
h2 {
font-size: 1.25rem;
margin: 0 0 0.5rem;
}
p {
color: #555;
font-size: 0.95rem;
margin: 0;
}
}
}
.blogDetail {
max-width: 720px;
margin: 2rem auto;
padding: 1.5rem;
background: #fff;
border-radius: 12px;
border: 1px solid #eee;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
h1 {
font-size: 2rem;
margin-bottom: 1rem;
}
p {
line-height: 1.7;
color: #333;
}
}
5. ๋ค๋น๊ฒ์ด์ ์ ๋ธ๋ก๊ทธ ์ถ๊ฐ
src/app/layout.tsx
โ <nav>
์์ ์ถ๊ฐ:
<Link href="/blog">๋ธ๋ก๊ทธ</Link>
6. ์ค๋์ ์ ๋ฆฌ
/blog
: ๊ธ ๋ชฉ๋ก โ JSON API ์ฐ๋/blog/[id]
: ๊ธ ์์ธ โ ๋์ ๋ผ์ฐํ- SCSS๋ก ๋ธ๋ก๊ทธ ์คํ์ผ๋ง
- Vercel ๋ฐฐํฌ ์
https://ํ๋ก์ ํธ์ฃผ์.vercel.app/blog
๋ก ์ ๊ทผ ๊ฐ๋ฅ
๐ฌ ๋๊ธ
โป ๋ก๊ทธ์ธ ํ ๋๊ธ์ ์์ฑํ ์ ์์ต๋๋ค.