[Prisma2] Cascade(onDelete), Set Null 구현
2021. 5. 19. 14:16

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" 옵션을 추가하지 않으면 사진은 삭제되지 않고 하위 항목들만 삭제되거나 연결이 끊어진다.

 

끝~!

퓨어맥스
퓨어맥스
의미있는 기록을 남기기 위해 시작한 개발 블로그 입니다. 사랑해주세요~❤️