티스토리 뷰

1. 개요

model User {
  id         Int        @id @default(autoincrement())
  username   String     @unique
  email      String?    @unique
  password   String?
  phone      String?    @unique
  github_id  String?    @unique
  avatar     String?
  created_at DateTime   @default(now())
  updated_at DateTime   @updatedAt
  SMSToken   SMSToken[]
  Product    Product[]
  Post       Post[]
  Comment    Comment[]
  Like       Like[]
}

model Post {
  id          Int      @id @default(autoincrement())
  title       String
  description String?
  views       Int      @default(0)
  created_at  DateTime @default(now())
  updated_at  DateTime @updatedAt

  user     User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId   Int
  comments Comment[]
  likes    Like[]
}

model Comment {
  id         Int      @id @default(autoincrement())
  payload    String
  created_at DateTime @default(now())
  updated_at DateTime @updatedAt

  user   User @relation(fields: [userId], references: [id], onDelete: Cascade)
  post   Post @relation(fields: [postId], references: [id], onDelete: Cascade)
  userId Int
  postId Int
}

 

 유저, 게시물, (게시물의) 댓글 모델이 이렇게 존재한다. 그리고 특정 게시물의 모든 댓글들을 가져오는 함수 코드를 아래처럼 작성했다. 

 

async function getComments(postId: number) {
  try {
    const comments = await db.comment.findMany({
      where: {
        postId,
      },
      select: {
        id: true,
        payload: true,
      },
      include: {
        user: {
          select: {
            username: true,
            avatar: true,
          },
        },
      },
    });

    return comments;
  } catch (e) {
    console.error(e);
    return [];
  }
}

 

 

상품에 대한 정보를 가져오는 함수에서 include라는 것을 이용해 user의 정보를 가져오는 것을 떠올려서 이를 적용해보았다. 하지만 위의 이미지처럼 에러가 발생했다.

 

2. 원인 

 Prisma에서는 select와 include를 동시에 사용하지 못하게 한다. 이는 데이터 선택의 모호성을 피하고 명확한 데이터 반환 구조를 보장하기 위함이다. 우선 공식 문서의 가장 첫 부분에 이렇게 설명되어 있다.

  • select: 특정 필드를 선택하는데 사용됨. 관계 필드도 중첩된 select를 사용해 포함할 수 있음.
  • include: 관계 데이터를 명시적으로 포함시키는데 사용됨.

둘을 동시에 사용하는 것은 어떤 필드를 포함해야 하고 어떤 관계를 가져와야 하는지에 대한 모호성을 초래할 수 있기에, 하나의 방법만을 사용하도록 데이터를 가져오도록 제한한다. 즉 select를 사용하여 필요한 필드만 가져오거나, include를 통해 연관된 데이터를 포함하는 방식을 선택해야 한다.

 

3. 해결 방법

 select만 이용하거나 include만을 이용하게 수정하면 된다. 

 

3-1. include를 이용한 방법

async function getComments(postId: number) {
  try {
    const comments = await db.comment.findMany({
      where: {
        postId,
      },
      include: {
        user: {
          select: {
            username: true,
            avatar: true,
          },
        },
      },
    });

    return comments;
  } catch (e) {
    console.error(e);
    return [];
  }
}

 

comments 출력 결과

 

include를 통해 user의 username과 avatar만 선택하였다. 이 때 id와 payload 등 comment의 속성들은 별도로 작성하지 않았는데 이는 기본적으로 가져오는 필드이기 때문에 별도로 지정하지 않아도 되기 때문이다.

 

3-2. select만 사용한 방법

async function getComments(postId: number) {
  try {
    const comments = await db.comment.findMany({
      where: {
        postId,
      },
      select: {
        id: true,
        payload: true,
        user: {
          select: {
            username: true,
            avatar: true,
          },
        },
      },
    });

    return comments;
  } catch (e) {
    console.error(e);
    return [];
  }
}

 

comments 출력 결과

 

이 경우는 created_at 등의 속성이 없는데, select를 통해 명시하지 않았기 때문이다.

 


공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함