NestJS | TypeORM, Mysql 연동하기

Sua·2021년 3월 27일
7

NestJS

목록 보기
5/9
post-thumbnail

NestJS에서 TypeORM, Mysql을 사용하는 방법에 대해 알아보자.

nest new 프로젝트명 명령어로 프로젝트를 생성하면 여러 파일들이 만들어진다. 그 중 app.module.ts 파일을 기억해두자.

NestJS 초기세팅에 대해 자세히 알고 싶다면 이 포스팅을 참고하면 된다.

이제 우리가 사용할 DB인 Mysql과 NestJS를 연동해줄 것이다. ORM은 TypeORM을 사용한다.

TypeORM 패키지 설치

우선 TypeORM을 설치하자.

npm install --save @nestjs/typeorm typeorm mysql2

NestJS에서 제공하는 TypeORM 패키지를 설치한다. DB로는 Mysql를 사용할 것이기 때문에 mysql2를 선택했다. 다른 DB를 선택하는 것도 가능하다.

Mysql은 이미 설치되어 있어야 한다. 만약 설치가 안 되어 있다면 이 포스팅을 참고해서 설치하자.

설치가 완료되었으면 본격적으로 데이터베이스 연동을 시도헤보자.

공식문서에 따르면 데이터베이스 연동하는 방법은 2가지이다.

1.app.module.ts 파일에 설정하는 방법
2. 프로젝트 루트 디렉토리에 ormconfig.json 파일을 생성해서 설정하는 방법

방법1: app.module.ts

// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [User, Product], // 사용할 entity의 클래스명을 넣어둔다.
      synchronize: true, // false로 해두는 게 안전하다.
    }),
  ],
})
export class AppModule {}

app.module.ts에서 TypeOrmModule을 import해서 사용할 수 있다. TypeOrmModule의 forRoot() 메서드 인자로 DB 정보를 넣어두면 연동이 된다.

여기서 forRoot()가 TypeORM에서 DB 연동할 때 사용하는 createConnection() 함수 역할을 해주고 있다고 보면 된다.

TypeORM Connection에 대한 문서

synchronize

Setting synchronize: true shouldn't be used in production - otherwise you can lose production data.

방법2: ormconfig.json

app.module.ts 파일의 forRoot()에 설정값을 직접 입력하지 않고, 루트 디렉토리에 ormconfig.json 파일을 만들어서 설정하는 방법이다.

// ormconfig.json
{
  "type": "mysql",
  "host": "localhost",
  "port": 3306,
  "username": "root",
  "password": "root",
  "database": "test",
  "entities": ["dist/**/*.entity{.ts,.js}"],
  "synchronize": true
}
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [TypeOrmModule.forRoot()],
})
export class AppModule {}

forRoot()에서 DB 접근 정보를 주지 않으면, 루트 경로의 ormconfig.json의 파일에서 설정 값을 자동으로 찾아 사용한다.

장점

DB 비밀번호라던지 민감한 정보들이 있으므로 파일을 따로 만들어 보관하는 편이 보안 측면에 좋다. 나중에 gitignore에 추가해서 이 파일만 빼고 깃허브에 올릴 수도 있다.

단점1

forRoot() 메소드를 통해 사용할 수 있었던 추가적인 설정들을 바로 사용할 수 없다.
추가적인 설정 속성에는 autoLoadEntities, retryDelay 등이 있다.

예를 들어 첫 번째 방법에서는 이렇게 설정을 추가해주기만 하면 된다.

// app.module.ts
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [],
      synchronize: true,
      autoLoadEntities: true, // 추가!!
    }),
  ],
})

다행히도 두 번째 방법에서도 답이 없는 건 아니다. 바로 getConnectionOptions을 사용하면 된다.

// app.module.ts
TypeOrmModule.forRootAsync({
  useFactory: async () =>
    Object.assign(await getConnectionOptions(), {
      autoLoadEntities: true,
    }),
})

단점2

ormconfig.json 파일을 사용한다면 내가 사용할 entity를 경로로 설정할 수밖에 없다. "entities": ["dist/**/*.entity{.ts,.js}"] 이렇게 말이다. 이렇게 되면 모든 entity가 실제 DB상의 테이블로 만들어진다. 하지만, entity 중에서 실제 테이블로 만들면 안 되는 것들이 있다. 예를 들어 그저 다른 테이블에서 참고하기 위해 만들어진 entity 말이다.

https://github.com/typeorm/typeorm/issues/1654

이 사이트에 따르면 아래와 같은 식으로 내가 원하는 파일을 제외할 수 있다고 한다.

{
    entities: ['src/entity/**/!(*.test.ts)']
}

(2021.04.16 추가)
실제로 데이터베이스에 테이블을 만들고 싶지 않은 클래스는 @entity 데코레이터를 달아주지 않으면 된다!
이런 식으로 추상 클래스를 선언한 다음 확장해서 사용할 수 있다.

export abstract class Content {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @Column()
  description: string
}

@Entity()
export class Photo extends Content {
  @Column()
  size: string
}

참고사이트 : https://yangeok.github.io/orm/2020/12/14/typeorm-decorators.html

profile
Leave your comfort zone

0개의 댓글