Ch 01. 프로젝트 설계와 데이터 모델
집을 짓기 전에 설계도가 있어야 합니다. 코드를 쓰기 전에 무엇을 만들지, 데이터가 어떻게 생겼는지 먼저 그려봐야 합니다. 나중에 설계를 바꾸는 것은 공사 도중 벽을 뜯는 것만큼 힘든 일입니다.
블로그 기능 목록
우리가 만들 블로그의 기능을 정리합니다.
| 기능 | 설명 | 인증 필요 |
|---|---|---|
| 글 목록 | 모든 글을 최신순으로 보기 | 불필요 |
| 글 상세 | 특정 글 읽기 | 불필요 |
| 글 작성 | 마크다운으로 새 글 쓰기 | 필요 |
| 글 수정 | 본인이 쓴 글 수정 | 필요 (작성자) |
| 글 삭제 | 본인이 쓴 글 삭제 | 필요 (작성자) |
| 댓글 작성 | 글에 댓글 달기 | 필요 |
| 댓글 삭제 | 본인 댓글 삭제 | 필요 (작성자) |
| 회원가입 | 이메일로 계정 생성 | 불필요 |
| 로그인 | 이메일/비밀번호 로그인 | 불필요 |
폴더 구조
my-blog/├── app/│ ├── (auth)/ # 인증 관련 라우트 그룹│ │ ├── login/page.tsx│ │ └── register/page.tsx│ ├── posts/│ │ ├── page.tsx # 글 목록│ │ ├── [slug]/│ │ │ └── page.tsx # 글 상세│ │ └── new/page.tsx # 글 작성│ ├── dashboard/│ │ └── page.tsx # 내 대시보드│ ├── api/│ │ └── auth/[...nextauth]/route.ts│ ├── layout.tsx│ └── page.tsx # 홈├── components/ # 재사용 컴포넌트│ ├── Header.tsx│ ├── PostCard.tsx│ └── CommentList.tsx├── lib/│ ├── prisma.ts # Prisma 클라이언트 싱글턴│ └── actions.ts # Server Actions├── prisma/│ └── schema.prisma├── auth.ts├── middleware.ts└── next.config.ts
ERD: 데이터 모델 관계
세 테이블이 중심입니다.

관계를 정리하면 이렇습니다.
- User는 여러 개의 Post를 가질 수 있습니다. (1:N)
- User는 여러 개의 Comment를 가질 수 있습니다. (1:N)
- Post는 여러 개의 Comment를 가질 수 있습니다. (1:N)
Prisma 스키마 작성
# Prisma 설치npm install prisma @prisma/clientnpm install -D prisma# 초기화 (PostgreSQL 사용)npx prisma init --datasource-provider postgresql```text`.env`에 데이터베이스 URL을 설정합니다.```bash# 파일: .envDATABASE_URL="postgresql://user:password@localhost:5432/myblog"```text스키마를 작성합니다.```prisma// 파일: prisma/schema.prismagenerator client { provider = "prisma-client-js"}datasource db { provider = "postgresql" url = env("DATABASE_URL")}model User { id String @id @default(cuid()) email String @unique name String password String role String @default("user") posts Post[] comments Comment[] createdAt DateTime @default(now()) @@map("users")}model Post { id String @id @default(cuid()) title String content String slug String @unique published Boolean @default(false) author User @relation(fields: [authorId], references: [id], onDelete: Cascade) authorId String comments Comment[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("posts")}model Comment { id String @id @default(cuid()) content String post Post @relation(fields: [postId], references: [id], onDelete: Cascade) postId String author User @relation(fields: [authorId], references: [id], onDelete: Cascade) authorId String createdAt DateTime @default(now()) @@map("comments")}```text마이그레이션을 실행해 실제 테이블을 생성합니다.```bashnpx prisma migrate dev --name init```text### Prisma 클라이언트 싱글턴개발 환경에서 Next.js는 핫 리로드 때마다 모듈을 재실행합니다. 매번 새 Prisma 클라이언트를 만들면 데이터베이스 연결이 폭발적으로 늘어납니다. 싱글턴 패턴으로 해결합니다.```typescript// 파일: lib/prisma.tsimport { PrismaClient } from "@prisma/client";const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined;};export const prisma = globalForPrisma.prisma ?? new PrismaClient({ log: process.env.NODE_ENV === "development" ? ["query"] : [], });if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
globalThis에 Prisma 클라이언트를 저장해 핫 리로드 후에도 같은 인스턴스를 재사용합니다.
다음 챕터에서는 마크다운 파일로 정적 블로그 글을 만드는 SSG 방식을 구현합니다.