prisma 사용기 2 - repository가 필요한가?

김지원·2022년 10월 11일
0

prisma

목록 보기
2/3

앞의 글 다음에 너무 늦게 쓰게 되는 사용기 글이네요ㅠㅠ

결론만 말하자면 굳이 필요없다!!!입니다.

이유는 차차 알아보도록 하고 일단 prisma에서 generate하게 되면 어떤 일이 벌어지는지 확인해보겠습니다.

어디에 있니..? 내 모델?

prisma는 schema.prisma에 모델을 정의하고 generate하게 되면 index.d.ts에 모든 명시한 모든 모델과 명령어들을 만들어줍니다.

예를 들자면 typeorm.repository.findOne() 메서드같은 느낌입니다.

prisma는 좀 더 세세하게 분리가 되지만 일단 그렇게 알아두시면 편합니다.ㅎㅎ

정확한 루트는 이것입니다.
node_module/.prisma/client/index.d.ts

아무튼 이건 아무런 상관이 없죠 우리는 가져다 쓰기만 해주면 됩니다.

  • model
    model

  • create(친절한 설명은 덤)
    create

어떻게 가져다가 쓸 수 있을까?

물론 여러가지 방법이 있습니다.

그 중에서 저는 prismaService를 하나 만들어서 PrismaClient에서 확장시켜 사용했습니다.
가장 큰 이유는 logger 때문이었습니다.

import { Prisma, PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService
  extends PrismaClient<Prisma.PrismaClientOptions, 'query' | 'error'>
  implements OnModuleInit
{
  private readonly logger = new Logger(PrismaService.name);
  constructor(private readonly configService: ConfigService) {
    super({
      log: [
        {
          emit: 'event',
          level: 'query',
        },
        {
          emit: 'event',
          level: 'error',
        },
        {
          emit: 'stdout',
          level: 'info',
        },
        {
          emit: 'stdout',
          level: 'warn',
        },
      ],
    });
  }
  async onModuleInit() {
    if (this.configService.get('NODE_ENV') === 'development') {
      this.$on('query', (event) => {
        this.logger.verbose(event.query, event.duration);
      });
    }

    this.$on('error', (event) => {
      this.logger.verbose(event.target);
    });

    await this.$connect();
  }
}

그래서 추가로 에러 부분과 개발 환경에서만 쿼리를 어떻게 날리는지 확인해주었습니다.

PrismaService도 만들어줬으니 그대로 가져가서 확장하여 사용하면 되겠죠?

근데 여기서 고민이 생깁니다..

repository와 entity를 굳이 만들어야할까?

이렇게 메서드가 다 짜여있다면 service단에서 모든게 해결되고 repository가 필요없는거 아닐까?

typeorm처럼 service에서 dto -> entity 컬럼들로 스위칭해줘야 될 필요도 없기 때문에 모든 작업은 service에서 하게 되지 않나?

typeorm (entity 종속)

const entities = new BoardEntity();
entities.title = dto.title;
entities.context = dto.context;

await this.repository.insert(entities);

(이 부분이 필요없다!)

라는 의문이 들었습니다.

하지만!

제가 생각한 문제점은 2가지가 있었습니다.

  1. swagger 문서를 더 편리하게 작성하려면 entity가 필요하다.
  2. service단에서 모든 것을 해결하면 코드가 더러워보일 것 같다.

결국..

많은 고민이 있었지만

repository에서 db 쿼리에 관련된 작업들을 실행하고
service는 input과 output을 관련하도록 작업을 분리하였습니다.

board.service.ts

  async getAll(selectBoardDto: SelectBoardDto): Promise<board[]> {
    !selectBoardDto.orderBy
      ? (selectBoardDto.orderBy = 'desc')
      : selectBoardDto.orderBy;

    return await this.boardsRepository.getAll(selectBoardDto);
  }

board.repository.ts

  async getAll({ skip, take, orderBy }: SelectBoardDto): Promise<board[]> {
    return this.repository.board.findMany({
      skip,
      take,
      orderBy: {
        id: orderBy,
      },
    });
  }
  • 에러처리는 전역 validator로 실행하였습니다.

간단한 전체 조회는 이렇게 보이지만 다른 조건문 같은 경우는 좀 더 깔끔하게 정리할 수 있는 결과를 기대해볼만 한 것 같습니다ㅎㅎ

그리고 entity는 swagger때문에 굳이 만들긴 했는데 entity없이 반환값을 나타낼 수 있다면 댓글로 남겨주시면 감사하겠습니다!

profile
backend-developer

4개의 댓글

comment-user-thumbnail
2022년 12월 10일

트랜젝션 함수 내에서 레포지토리에 있는 함수를 불러와서 처리할 수 있나요?

1개의 답글
comment-user-thumbnail
2022년 12월 19일

같은 고민하고 있었고, 같은 방식으로 적용하고 있습니다.
확실히 service에서는 직접 prisma 를 사용하는 것 보다 repository에 정의되어 있는 함수를 호출하는 것이 더 가독성이 좋아 보이더라구요.
좋은 글 감사합니다.

1개의 답글