Prisma를 사용한 프로젝트 관리 도구 구축하기

Trello와 같은 협업 프로젝트 관리 도구를 구축하고 있습니다.

React, Express.js, PostgreSQL, 그리고 Socket.io를 사용하고 있습니다. 백엔드 라우트를 작성하기 전에 데이터베이스 스키마를 먼저 설계해야 합니다.

스키마는 기초입니다. 스키마가 잘못되면 앱 전체가 실패합니다. 제가 설계한 Prisma 스키마의 상세 내용은 다음과 같습니다.

모델 (The Models)

• User: 이름, 이메일, 비밀번호를 저장합니다. ID에는 cuid()를 사용합니다. 이는 길고 고유한 문자열을 생성합니다. URL을 통해 사용자 수를 노출하지 않기 때문에 숫자형보다 더 좋습니다.

• Project: 프로젝트 이름과 설명을 저장합니다. 물음표를 사용하여 설명을 선택 사항(optional)으로 만들었습니다.

• ProjectMember: 이 테이블은 교차 테이블(junction table)입니다. User와 Project를 연결합니다. 한 명의 사용자가 여러 프로젝트에 참여할 수 있고, 한 프로젝트에 여러 사용자가 있을 수 있으므로, 다대다(many-to-many) 관계를 관리하기 위해 이 중간 테이블이 필요합니다. 동일한 사용자가 프로젝트에 중복으로 참여하는 것을 방지하기 위해 고유 제약 조건(unique constraint)을 추가했습니다.

• Board: Task는 Board 안에 존재하며, Board는 Project 안에 존재합니다. 이러한 계층 구조 덕분에 드래그 앤 드롭을 쉽게 구현할 수 있습니다. 컬럼 간에 Task를 이동하는 것은 단순히 필드 하나를 업데이트하는 작업일 뿐입니다.

• Task: 핵심 모델입니다. User 모델과 두 가지 서로 다른 관계를 가집니다:

• Comment: 사용자는 Task에 댓글을 남길 수 있습니다. 코드의 가독성을 높이기 위해 관계 이름을 "user" 대신 "author"로 지정했습니다.

• Notification: 사용자를 위한 메시지를 추적하는 간단한 모델입니다.

기술적 교훈 (Technical Lessons Learnt)

구축 과정에서 몇 가지 오류를 겪었습니다. 다음 사항들을 주의하세요:

이제 스키마 마이그레이션이 완료되었습니다. 다음 단계로는 실시간 업데이트를 위한 Express 백엔드와 Socket.io 설정을 구축할 예정입니다.

처음부터 프로젝트 관리 도구 구축하기: Prisma 스키마부터 시작하기

이 글에서는 처음부터 프로젝트 관리 도구를 구축해 보겠습니다. 모든 애플리케이션에서 가장 중요한 부분인 데이터베이스 스키마부터 시작할 것입니다. 스키마를 정의하기 위해 차세대 ORM인 Prisma를 사용할 것입니다.

왜 Prisma인가?

Prisma는 데이터베이스 접근을 쉽고 타입 안전(type-safe)하게 만들어주는 차세대 ORM입니다. Prisma를 사용하면 데이터베이스 스키마를 정의하고, 타입이 지정된 클라이언트를 생성하며, 데이터베이스 마이그레이션을 쉽게 관리할 수 있습니다.

프로젝트 설정

먼저, 새로운 프로젝트를 초기화하고 Prisma를 설치해야 합니다.

mkdir project-management-tool
cd project-management-tool
npm init -y
npm install prisma --save-dev
npx prisma init

이 명령어를 실행하면 prisma 폴더와 .env 파일이 생성됩니다. prisma/schema.prisma 파일이 우리가 스키마를 정의할 곳입니다.

스키마 정의하기

이제 프로젝트 관리 도구에 필요한 모델을 정의해 보겠습니다. 우리의 도구에는 사용자(User), 워크스페이스(Workspace), 프로젝트(Project), 그리고 작업(Task)이 필요합니다.

User 모델

먼저 User 모델을 정의합니다. 사용자는 이메일, 이름, 그리고 생성/수정 시간을 가집니다.

model User {
  id        String     @id @default(uuid())
  email     String     @unique
  name      String?
  createdAt DateTime   @default(now())
  updatedAt DateTime   @updatedAt
  workspaces Workspace[]
  tasks      Task[]
}

Workspace 모델

워크스페이스는 프로젝트를 담는 컨테이너 역할을 합니다. 각 워크스페이스는 소유자(Owner)를 가집니다.

model Workspace {
  id        String    @id @default(uuid())
  name      String
  ownerId   String
  owner     User      @relation(fields: [ownerId], references: [id])
  projects  Project[]
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
}

Project 모델

프로젝트는 특정 워크스페이스에 속합니다.

model Project {
  id          String     @id @default(uuid())
  name        String
  description String?
  workspaceId String
  workspace   Workspace  @relation(fields: [workspaceId], references: [id])
  tasks       Task[]
  createdAt   DateTime