프레임워크/TypeORM

TypeORM 0.3에서 Seeding 하기

SpaceCowboy 2023. 2. 13. 23:47

참고

Seeder란?

데이터베이스에 초기 데이터 및 테스트 용 더미 데이트를 입력해주는 도구입니다.

  • 권한 정보나 관리자 계정같은 데이터는 초기에 필요한 정보인데 이를 Seeder를 사용해서 미리 입력할 수 있습니다.
  • 테스트할 때 필요한 데이터들을 편리하게 채워넣을 수 있습니다.

우선 셋업을 설명하기 전에, 보통 TypeORM Seeding을 위해서 구글링을 해보면 typeorm-seeding이라는 패키지를 사용한다는걸 알 수 있습니다. 하지만 두 가지 이유로 비추천합니다.

  • 더 이상 관리되고 있지 않음: 여기에서 확인해보시면 마지막 업데이트가 3년전입니다.
  • 따라서 여전히 ormconfig를 사용해야함: dataSource 사용이 좀 더 권장됩니다. 왜 ormconfig를 쓰면 안되는지는 여기에서 확인하실 수 있습니다.

그래서 제가 찾아본 패키지는 typeorm-extension이라는 패키지입니다.

  • https://www.npmjs.com/package/typeorm-extension
  • 지속적으로 관리되고 있습니다. - 2023년 2월 12일 기준으로 한달 전까지 업데이트가 있었군요!
  • TypeORM 공식문서에도 소개되어있습니다! - 여기를 보시면 확인하실 수 있습니다. 신뢰도가 상승하는군요…
  • dataSource를 사용합니다.

TypeORM Seeding 셋업 및 실행

TypeORM Migration 을 읽고 오셨다는 가정하에 진행됩니다.

typeorm-extension 패키지를 통해 seeding 셋업을 진행해봅시다.

npm install typeorm-extension --save

package.jsonscripts 섹션에 다음 스크립트를 넣습니다.

"seed": "ts-node -r tsconfig-paths/register ./node_modules/typeorm-extension/dist/cli/index.js seed",

typeorm-extension cli의 경우에도 절대경로를 이해하지 못해서 tsconfig-paths 패키지를 활용한 모습입니다.

- typeorm-extension은 DataSource 파일의 디폴트 경로로 루트 디렉토리의 data-source.ts 파일을 찾습니다. 따로 지정할 수 있습니다.
- typeorm-extension의 seed 명령어는 seeder 파일의 디폴트 경로를 src/database/seeds/**/*{.ts,.js} 로 간주합니다. 따로 지정할 수 있습니다.

typeorm-extension 패키지도 typeorm의 dataSource를 사용하기 때문에 data-source.ts 가 필요할거같네요. 루트 디렉토리에 추가했습니다.

import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
import { DataSource } from 'typeorm';

config();

const configService = new ConfigService();

export default new DataSource({
  type: 'mysql',
  host: configService.get('DB_HOST'),
  port: configService.get<number>('DB_PORT'),
  username: configService.get('DB_USERNAME'),
  password: configService.get('DB_PASSWORD'),
  database: configService.get('DB_DATABASE'),
  synchronize: false,
  entities: ['src/**/*.entity.ts'],
  migrations: ['src/database/migrations/*.ts'],
  migrationsTableName: 'migrations',
});

이제 우리의 Cat Entity에 대한 초기 데이터 삽입을 위해서 src/database/seeds 경로에 cats.seeder.ts 파일을 추가합니다.

해당 파일에서 어떤 데이터를 넣을지 정의하면 됩니다.

import { Cat } from 'src/cats/entities/cat.entity';
import { DataSource } from 'typeorm';
import { Seeder } from 'typeorm-extension';

export default class CatsSeeder implements Seeder {
  async run(dataSource: DataSource): Promise<any> {
    const repository = dataSource.getRepository(Cat);
    await repository.insert([
      {
        name: 'cat1',
        kind: 'cat',
      },
    ]);
  }
}

보시다시피, typeorm-extension의 Seeder를 구현했습니다. 그리고 내부적으로 DataSource를 주입받고 repository를 사용해서 실제 데이터를 입력하는 방식으로 진행된다는걸 알 수 있습니다.

이제 터미널에서 다음 명령어를 실행합니다.

npm run seed

다음과 비슷한 화면이 나오면 성공한겁니다.

따로 성공했다는 메시지는 없습니다.

실제로 데이터가 잘 들어갔는지 확인하기 위해, MySQL Workbench로 확인해봤습니다.

잘 들어갔네요.

랜덤 데이터 삽입하기 feat. Faker, Factory

위의 과정에서는 우리가 임의로 정한 데이터만 삽입하는 과정이였고 랜덤한 데이터가 입력되게 하고 싶을 수도 있습니다.

typeorm-extension에서는 factory라는 기능을 통해서 랜덤한 데이터를 입력할 수 있습니다.

src/database/factories 디렉토리에 cats.factory.ts 파일을 추가합니다.

typeorm-extension은 factory 파일의 디폴트 디렉토리를 src/database/factories로 간주합니다. 따로 지정할 수 있습니다.

import { Cat } from 'src/cats/entities/cat.entity';
import { setSeederFactory } from 'typeorm-extension';

export default setSeederFactory(Cat, (faker) => {
  const cat = new Cat();
  cat.name = faker.name.fullName();
  cat.kind = faker.animal.cat();

  return cat;
});

cats.seeder.ts 의 코드를 수정합니다.

import { Cat } from 'src/cats/entities/cat.entity';
import { DataSource } from 'typeorm';
import { Seeder, SeederFactoryManager } from 'typeorm-extension';

export default class CatsSeeder implements Seeder {
  async run(
    dataSource: DataSource,
    factoryManager: SeederFactoryManager,
  ): Promise<any> {
    const repository = dataSource.getRepository(Cat);
    // await repository.insert([
    //   {
    //     name: 'cat1',
    //     kind: 'cat',
    //   },
    // ]);

    const catsFactory = factoryManager.get(Cat);
    await catsFactory.saveMany(5);
  }
}

SeederFactoryManager를 주입받아서 다음과 같은 동작을 합니다.

  • get 메서드를 통해서 Entity에 관련된 factory를 얻습니다. 해당 Entity와 관련된 factory가 src/database/factories에 존재해야합니다.
  • saveMany 메서드를 통해 원하는 개수만큼 랜덤 데이터를 입력할 수 있습니다.

이후 npm run seed 명령어를 실행하고나서 DB를 보면 랜덤한 데이터가 생성되어 있는 것을 보실 수 있습니다.

5번부터 9번까지 랜덤하게 생성된것을 느낄 수 있습니다.

그 외

  • typeorm-extension 공식문서를 보시면 아시겠지만 굳이 Seeding 뿐만 아니라 다양한 용도로 쓸 수 있습니다. 직접 확인해보세요