Prisma는 스키마 파일(schema.prisma)에서 모델 간의 관계를 직관적으로 정의할 수 있도록 해줍니다. @relation 속성을 사용하여 관계의 세부 사항을 설정할 수 있습니다.

기본 관계 필드 설정 원리

  • 외래 키(Foreign Key): 관계의 "N"쪽에 해당하는 모델에 외래 키 필드를 정의합니다. 이 필드는 관계의 "1"쪽 모델의 기본 키를 참조합니다.
  • 관계 필드: 양쪽 모델에 서로를 참조하는 관계 필드를 정의합니다. 이 필드는 데이터베이스에 실제 컬럼으로 생성되지 않고, Prisma Client가 관계를 탐색하는 데 사용됩니다.
  • @relation 속성: 관계 필드에 @relation 속성을 사용하여 관계의 상세 정보를 설정합니다.
    • fields: 외래 키 필드를 지정합니다.
    • references: 외래 키 필드가 참조할 대상 모델의 기본 키 필드를 지정합니다.
    • name (선택 사항): 모호한 관계를 명확히 할 때 사용합니다.

1. 1:1 관계 (One-to-One)

1:1 관계는 한 모델의 레코드가 다른 모델의 레코드와 정확히 하나씩 연결되는 관계입니다. 일반적으로, 한쪽 모델이 다른 쪽 모델의 외래 키를 가지고 있습니다.

예시: 사용자(User)와 프로필(Profile)
한 사용자는 하나의 프로필을 가지고, 하나의 프로필은 한 명의 사용자에게 속합니다.

// schema.prisma

model User {
  id      Int     @id @default(autoincrement())
  email   String  @unique
  name    String?
  profile Profile? // User가 Profile을 가질 수도 있고 없을 수도 있음 (Optional)
}

model Profile {
  id       Int    @id @default(autoincrement())
  bio      String?
  userId   Int    @unique // 외래 키 (User 모델의 id를 참조)
  user     User   @relation(fields: [userId], references: [id]) // User 모델과의 관계 필드
}

설명:

  • Profile 모델에 userId 필드가 외래 키로 정의되어 User 모델의 id를 참조합니다.
  • @unique 제약 조건이 userId에 추가되어 1:1 관계를 강제합니다. (하나의 Profile은 오직 하나의 User에만 연결될 수 있습니다.)
  • Profile 모델의 user 필드는 User 모델을 참조하는 관계 필드이며, userId 필드를 통해 User.id를 참조하도록 @relation이 설정되어 있습니다.
  • User 모델의 profile 필드는 Profile 모델을 참조하는 관계 필드입니다. ?는 프로필이 선택 사항임을 나타냅니다.

2. 1:N 관계 (One-to-Many)

1:N 관계는 한 모델의 레코드가 다른 모델의 여러 레코드와 연결될 수 있는 관계입니다. 가장 흔한 관계 유형입니다.

예시: 게시물(Post)과 댓글(Comment)
하나의 게시물은 여러 개의 댓글을 가질 수 있지만, 하나의 댓글은 오직 하나의 게시물에만 속합니다.

// schema.prisma

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  authorId  Int
  author    User     @relation(fields: [authorId], references: [id]) // Post를 작성한 User (선택 사항)
  comments  Comment[] // Post가 여러 개의 Comment를 가질 수 있음
}

model Comment {
  id        Int      @id @default(autoincrement())
  content   String
  createdAt DateTime @default(now())
  postId    Int      // 외래 키 (Post 모델의 id를 참조)
  post      Post     @relation(fields: [postId], references: [id]) // Comment가 속한 Post
}

// User 모델은 위에서 정의된 User 모델을 사용합니다.
// Post를 작성한 User와의 관계도 포함했습니다.
model User {
  id      Int     @id @default(autoincrement())
  email   String  @unique
  name    String?
  posts   Post[] // User가 여러 개의 Post를 작성할 수 있음
  profile Profile?
}

설명:

  • Comment 모델에 postId 필드가 외래 키로 정의되어 Post 모델의 id를 참조합니다.
  • Comment 모델의 post 필드는 Post 모델을 참조하는 관계 필드이며, postId 필드를 통해 Post.id를 참조하도록 @relation이 설정되어 있습니다.
  • Post 모델의 comments 필드는 Comment 모델의 배열(Comment[])로 정의되어 하나의 Post가 여러 개의 Comment를 가질 수 있음을 나타냅니다.

3. M:N 관계 (Many-to-Many)

M:N 관계는 양쪽 모델의 레코드가 서로 여러 레코드와 연결될 수 있는 관계입니다. Prisma는 M:N 관계를 정의할 때 중간에 연결 테이블(Join Table)을 자동으로 생성하거나, 직접 생성할 수 있도록 지원합니다.

예시: 학생(Student)과 과목(Course)
한 학생은 여러 과목을 수강할 수 있고, 한 과목은 여러 학생이 수강할 수 있습니다.

// schema.prisma

model Student {
  id       Int       @id @default(autoincrement())
  name     String
  courses  Course[] // Student가 여러 개의 Course를 수강할 수 있음 (자동 생성된 연결 테이블 사용)
}

model Course {
  id       Int       @id @default(autoincrement())
  title    String
  students Student[] // Course에 여러 명의 Student가 수강할 수 있음 (자동 생성된 연결 테이블 사용)
}

설명:

  • StudentCourse 모델 모두에 서로를 참조하는 관계 필드를 배열([])로 정의합니다.
  • Prisma는 이 두 모델의 M:N 관계를 처리하기 위해 _StudentToCourse와 같은 이름의 **중간 연결 테이블(Join Table)**을 자동으로 생성합니다. 이 테이블은 studentIdcourseId라는 외래 키를 가집니다.
  • 개발자는 이 연결 테이블을 직접 스키마에 정의할 필요 없이 Prisma가 자동으로 처리해 줍니다.

만약 중간 연결 테이블에 추가 필드가 필요한 경우 (명시적 M:N)

수강 날짜, 성적 등 M:N 관계 자체에 속성이 필요한 경우, 중간 연결 테이블을 직접 모델로 정의해야 합니다.

예시: 학생(Student)과 과목(Course) - 수강(Enrollment) 모델을 통해 M:N 구현

// schema.prisma

model Student {
  id          Int          @id @default(autoincrement())
  name        String
  enrollments Enrollment[] // Student는 여러 개의 Enrollment를 가질 수 있음
}

model Course {
  id          Int          @id @default(autoincrement())
  title       String
  enrollments Enrollment[] // Course는 여러 개의 Enrollment를 가질 수 있음
}

// 명시적인 연결 테이블 (Enrollment)
model Enrollment {
  id          Int      @id @default(autoincrement())
  studentId   Int
  courseId    Int
  enrolledAt  DateTime @default(now()) // 추가 필드
  grade       String?                   // 추가 필드

  student     Student  @relation(fields: [studentId], references: [id])
  course      Course   @relation(fields: [courseId], references: [id])

  @@unique([studentId, courseId]) // 같은 학생이 같은 과목을 두 번 수강하지 못하도록
}

설명:

  • Enrollment라는 새로운 모델을 생성하여 StudentCourse 사이의 M:N 관계를 명시적으로 나타냅니다.
  • Enrollment 모델은 studentIdcourseId라는 외래 키를 가지며, 각각 StudentCourse 모델을 참조합니다.
  • enrolledAt, grade와 같은 관계에 대한 추가적인 속성을 Enrollment 모델에 직접 정의할 수 있습니다.
  • @@unique([studentId, courseId])를 통해 한 학생이 한 과목을 두 번 수강할 수 없도록 유니크 제약 조건을 추가했습니다.

공식 문서 링크

더 자세한 정보와 다양한 시나리오는 Prisma 공식 문서에서 확인하실 수 있습니다.

+ Recent posts