본문 바로가기

Backend/NestJS

[NestJS] @EntityRepository 대체 커스텀 데커레이터, 모듈 만들기

728x90
Repository 생성에 쓰인 @EntityRepository 데커레이터가 삭제되면서,
Repository 생성을 위한 CustomRepository을 공부한 기록이다.

개요

전체적인 Repository의 구조와 역할에 대해서는 지난 기록에서 다뤘다.

 

[NestJS] TypeORM, Entity, Repository 구조(NestJS PostgresSQL 적용)

드디어 DB 연동을 해봤다. NestJS에서 DB 연동에 필요한 개념과 전체적 구조에 대한 기록이다. 개요 NestJS에서 DB를 연동하는데 내가 이용한 개념은 TypeORM, Entity, Repository이다. TypeORM은 쉽게 TS를 사용

choi-records.tistory.com

 

이번 기록에서는 커스텀 모듈, 데커레이터 생성에 대해 기록하려고 한다.

지난 기록에서 볼 수 있듯 Repository는 Repository Pattern을 구현하기 위해 생성한다.

Repository Pattern은 쉽게 말해, 서비스 파일에서의 비즈니스 로직에서 DB 관련 로직을 분리하는 패턴이다.

 

즉, Repository에서 반드시 이루어져야 하는 작업은 entity와 연결되는 작업이다.(꼭 기억하자!)

커스텀 데커레이션

먼저 Repository 클래스임을 선언해 줄 클래스 데커레이션을 생성해 보자.

import { SetMetadata } from "@nestjs/common";

export const TYPEORM_EX_CUSTOM_REPOSITORY = "TYPEORM_EX_CUSTOM_REPOSITORY";

export function CustomRepository(entity: Function): ClassDecorator {
  return SetMetadata(TYPEORM_EX_CUSTOM_REPOSITORY, entity);
}

SetMetadata 메서드를 통해 key, value 쌍으로 문자열과 entity를 저장해 줌으로써,

해당 Repository의 메타데이터를 설정해 줬다.

Meta data
메타 데이터는 쉽게 말해 데이터의 데이터다.
데이터에 대한 설명을key, value 쌍으로 나타낸 데이터이다.

동적 모듈 생성

이제 가장 중요한 Repository를 entity와 연결해주는 작업이다.

이 작업을 동적 모듈을 통해 구현해 줄 것이다.

 

동적 모듈은 쉽게 말해 모듈이 provider가 구성되는 방식에 영향을 주는 

동적으로 provider를 설정하는 모듈이다.

import { DynamicModule, Provider } from '@nestjs/common';
import { getDataSourceToken } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { TYPEORM_EX_CUSTOM_REPOSITORY } from './typeorm-ex.decorator';

export class TypeOrmExModule {
  public static forCustomRepository<T extends new (...args: any[]) => any>(
    repositories: T[],
  ): DynamicModule {
    const providers: Provider[] = [];

    for (const repository of repositories) {
      const entity = Reflect.getMetadata(
        TYPEORM_EX_CUSTOM_REPOSITORY,
        repository,
      );

      if (!entity) {
        continue;
      }

      providers.push({
        inject: [getDataSourceToken()],
        provide: repository,
        useFactory: (dataSource: DataSource): typeof repository => {
          const baseRepository = dataSource.getRepository<any>(entity);
          return new repository(
            baseRepository.target,
            baseRepository.manager,
            baseRepository.queryRunner,
          );
        },
      });
    }

    return {
      exports: providers,
      module: TypeOrmExModule,
      providers,
    };
  }
}

위 모듈에서의 핵심은 repository 배열을 인자로 전달받고,

repository의 meta data에서 entity를 가져와 둘을 연결해주는 작업이다.

    for (const repository of repositories) {
      const entity = Reflect.getMetadata(
        TYPEORM_EX_CUSTOM_REPOSITORY,
        repository,
      );

Reflect.getMetadata를 통해 런타임에 meta data를 가져옴으로써

동적 모듈을 구현할 수 있게 했다.

 

meta data에서 repository를 통해 setMetadata의 value였던 entity를 가져온다.

      providers.push({
        inject: [getDataSourceToken()],
        provide: repository,
        useFactory: (dataSource: DataSource): typeof repository => {
          const baseRepository = dataSource.getRepository<any>(entity);
          return new repository(
            baseRepository.target,
            baseRepository.manager,
            baseRepository.queryRunner,
          );
        },
      });
    }

getDataSourceToken을 통해 Data Source 타입을 가져온다.

해당 타입을 통해 위에 보이는 getRepository 메서드를 사용할 수 있는데

이 메서드가 반환하는 값이 바로

 

entity와 연결된 repository

 

참고

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

typeorm 0.3.x @EntityRepository 돌려줘~~

typeorm 0.3.x 에서는 기존에 사용하던 @EntityRepository가 deprecated 되었다.그 말인 즉슨 커스텀 레포지토리 패턴을 사용할 수 없게되었다. 눈물이 난다.. 눈물이 나 하지만 의지의 한국인은 방법을 찾아

velog.io

마무리

얕게 이해한 정도라 부족한 점이 많습니다.

잘못된 정보 등의 피드백은 환영입니다.

감사합니다.

728x90