티스토리 뷰
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 [];
}
}
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 [];
}
}
이 경우는 created_at 등의 속성이 없는데, select를 통해 명시하지 않았기 때문이다.
'기록' 카테고리의 다른 글
Next.js의 private folders (0) | 2024.11.23 |
---|---|
Next.js에서 클라이언트 컴포넌트에서 환경변수 사용하기 (0) | 2024.11.17 |
Next.js의 Optimistic Update와 useOptimistic (0) | 2024.11.09 |
Prisma의 Composite Id 간단 기록 (0) | 2024.11.09 |
Next.js의 routing 관련: Route Segment Config, generateStaticParams, dynamicParams (0) | 2024.11.03 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- typescript
- CSS
- 동적계획법
- 코드스테이츠
- 햄버거버튼
- 자바스크립트
- 순열
- C++
- NextJS
- themoviedb
- BFS
- 완전탐색
- SQL
- 타입스크립트
- react
- 브루트포스
- Redux
- 리액트
- 스택
- 다이나믹프로그래밍
- aws
- 구현
- 비트마스킹
- Next.js
- async
- 프로그래머스
- 백준
- 알고리즘
- 카카오맵
- 넥스트js
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함