iBetter Books
수정

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: 데이터 모델 관계

세 테이블이 중심입니다.

블로그 ERD — User, Post, Comment 관계

관계를 정리하면 이렇습니다.

  • 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 방식을 구현합니다.