Prisma ORM 미들웨어 활용하기

tre2man
roubit.me
Published in
4 min readJun 4, 2022

현재 운영중인 서비스가 점점 커지면서, 현재 운영중인 서비스의 DB의 확장이 필요해 졌습니다. 😱 그래서 기존의 1개로 운영되는 DB를 master와 slave로 나누어서 운영하기로 했습니다.

이 때 저희가 사용중인 ORM에서는, 공식적으로는 master DB와 slave DB를 분리하여 접속하는 방법이 나와있지 않았습니다. 하지만 Prisma의 MiddleWare를 수정하여 DB를 분리할 수 있었습니다!

공식 문서 확인

위 글에 따르면, prisma 객체 생성 후 $use 메서드를 통해 prisma의 속성을 변경할 수 있는 것 같습니다! 매개변수로 params와 next를 받는 매개변수가 있는 것 같습니다. 이제 ts 파일을 뜯어 보겠습니다. 아래는 params의 타입인 MiddleWareParams의 타입입니다.

export type MiddlewareParams = { model?: ModelName action: PrismaAction args: any dataPath: string[] runInTransaction: boolean}

model은 테이블 이름, action은 createMany, deleteMany, findUnique 등의 prisma에서 사용할 수 있는 동작, args는 action의 매개변수에 들어갈 데이터 같습니다. 나머지는 중요하지 않아 보입니다. 해당 정보들을 바탕으로 코드를 해석해 보겠습니다.

코드 작성

onModuleInit() 메서드 안에서 prod 환경일 때 replica DB에 연결되는 prisma 객체에 연결했습니다. SELECT 동작 (find, query, count, aggregate 등의 동작들)일 경우에는 readOnlyInstance를 사용합니다. 위의 코드는 아래 링크에 있는 이슈를 참고했습니다.

Soft Delete 구현

여기서만 그치기에는 뭔가 아쉽습니다. 보통 DB를 설계할 때는 delete 동작에 대해서는 hard delete보다는 soft delete로 설계를 합니다. 혹시나 복구를 할 상황이 있을 수도 있기 때문입니다.

그래서 이러한 동작도 delete* 동작을 실행할 때 실제로 데이터가 삭제되는 것이 아닌 deletedAt 속성을 변경하는 동작으로 전환하고, SELECT* 동작을 할 때도 항상 filter에 deletedAt : null를 확인하게 하는 코드를 작성해 보았습니다. 🚀

action이 delete 또는 deleteMany일 경우 update, updateMany 동작으로 변경 후 deletedAt 항목을 new Date()로 변경합니다.

결과

두 코드를 합치게 되면, 다음과 같은 결과가 나오게 됩니다.

  • find, query 등의 SELECT 명령은 deletedAt : null을 기본 필터로 가져가고 replica DB에서만 조회합니다.
  • 나머지 동작 (create, update, delete)은 master DB에서 확인합니다.
  • delete 동작은 hard delete가 아닌 soft delete동작으로 변경됩니다.

위 글은 아래의 본문을 참고했습니다.

--

--