1. Casecade, Set Null 이해
model Photo {
... // 주요 내용만 보기 쉽게 나머지 요소들 생략(...은 실제 코드가 아님)
hashtags Hashtag[]
likes Like[]
Comment Comment[]
}
model Hashtag {
...
photos Photo[]
}
model Like {
...
photo Photo @relation(fields: [photoId], references: [id])
photoId Int
}
model Comment {
...
photo Photo @relation(fields: [photoId], references: [id])
photoId Int
}

위 코드는 프리즈마 데이터 모델 중 사진(Photo), 해시태그(Hashtag), 좋아요(Like), 댓글(Comment)의 관계를 나타낸 것이다.
지금부터 위 예시를 사용해서 설명하도록 하겠다.
- Cascade : 하위 항목이 상위 항목에 종속되는 것으로 상위 항목 삭제 시 연결된 하위 항목도 같이 삭제
- Set Null : 상위 항목과 하위 항목이 독립적(?) 위치를 갖는 것으로 상위 항목 삭제 시 연결된 하위 항목은 연결만 끊어짐(삭제X)
Prisma1에서는 특별한 명시가 없으면 Set Null이 자동으로 반영됐고, Cascade는
@relation(name: "XXXX", onDelete: CASCADE)
이런 식으로 코드에 명시만 하면 적용되도록 기능을 지원하였다.
하지만~! Prisma2에서는 이 기능을 지원하지 않는다....
따라서, 코드로 직접 관계를 끊어주거나 하위 항목을 삭제하는 코드를 작성해야 하는데..
이를 편하게 하기 위한 다양한 방법들 중 한 가지를 정리하려 한다.
(Prisma 공홈에서도 추천하는 방식이라고 하니 따로 자기들이 개발할 의지가 없는...?)
2. 예시 모델에서 관계(Cascade, Set Null) 설정
- 좋아요, 댓글 : 특정 사진 1개에 관계된 정보로 해당 사진이 사라지면 (일반적으로) 필요 없는 데이터이므로 Cascade로 설정
- 해시태그 : 사진 여러 개와 관계될 수 있고 추후 재활용될 수 있는 데이터로 Set Null로 설정

3. 모듈(@paljs/plugins)을 사용한 코드 작성
우선 아래 코드로 백앤드에 해당 모듈을 설치한다
https://paljs.com/plugins/delete/
npm i @paljs/plugins
그리고 상위 항목(사진, Photo) 모델의 하위 항목 바로 윗부분에 아래와 같이 코드 작성
model Photo {
...
/// @onDelete(SET_NULL)
hashtags Hashtag[]
/// @onDelete(CASCADE)
likes Like[]
/// @onDelete(CASCADE)
Comment Comment[]
}
위와 같이 작성 후 migrate 진행
(migrate를 해야 반영되는지는 정확히 모르겠지만, 필자는 하다가 잘 안돼서 migrate 하고 잘 된 것 같아서 써놈... 필요 없는 단계일 수도...)
다음 아래와 같이 설치한 모듈을 써서 상위 모델 삭제 코드 작성
import client from "../../client" //프리즈마 클라이언트 혹시 몰라서 아래에 코드블럭으로 써놈
import { PrismaDelete } from "@paljs/plugins"
// 모듈 정의
const prismaDelete = new PrismaDelete(client)
// Photo 삭제 정의
await prismaDelete.onDelete({
model: "Photo",
where: {
id: targetPhoto.id,
},
// 하위 항목 뿐만 아니라 자기 자신도 삭제한다는 의미
deleteParent: true,
})
// 위에서 쓰인 client의 정체
import { PrismaClient } from ".prisma/client"
const client = new PrismaClient()
export default client
위와 같이 작성하면 사진 삭제 시 아래로 연결된 하위 항목들도 같이 삭제되거나 연결을 끊어준다.
참고로 "deleteParent: true" 옵션을 추가하지 않으면 사진은 삭제되지 않고 하위 항목들만 삭제되거나 연결이 끊어진다.
끝~!