포시코딩

[Nest.js] 6. TypeORM 설치 및 세팅 - @nestjs/config 사용법 본문

Node.js

[Nest.js] 6. TypeORM 설치 및 세팅 - @nestjs/config 사용법

포시 2023. 2. 16. 11:12
728x90

TypeORM

설치

npm i @nestjs/typeorm typeorm mysql

 

세팅

app.module.ts

// ...생략

@Module({
  imports: [
    TypeOrmModule.forRoot({
      // DB 설정 관련 내용 기입
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'qwer1234',
      database: 'nest_prac',
      entities: [],
      synchronize: true,
    }),
    BoardModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

외부 모듈을 위에, 내부 모듈을 밑에 적는게 일반적이다.

 

synchronize: true에 대해서

entity를 통해 오버라이드 되며 테이블이 생성됨
개발 버전에서는 스키마의 용이한 수정을 위해 true로 사용하지만
배포 버전에서는 꼭! false여야 한다.

entity를 누군가 수정하면 테이블이 바뀌기 때문

 

근데 지금 보면 제일 먼저 보이는 모듈에 DB 정보가 고스란히 노출되고 있다.

보안상, 미관상으로 매우 보기 안좋기 때문에 감추고 싶은데

이럴때 보통 dotenv 패키지를 써서 감췄는데

 

Nest.js에서는 dotenv 대신 @nestjs/config를 사용한다.

 

@nestjs/config

설치

npm i @nestjs/config

mkdir src/config

 

세팅

config 폴더에 typeorm.config.service.ts 파일 생성 후 아래와 같이 작성해준다.

 

typeorm.config.service.ts

import { Injectable } from '@nestjs/common';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  createTypeOrmOptions(): TypeOrmModuleOptions {
    return {
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'qwer1234',
      database: 'nest_prac',
      entities: [],
      synchronize: true,
    };
  }
}

이제 아까 app.module.ts에 작성한 부분을 수정해준다.

 

app.module.ts

// ...생략

@Module({
  imports: [
    TypeOrmModule.forRootAsync({  // forRoot -> forRootAsync로 변경
      useClass: TypeOrmConfigService,  
    }),
    BoardModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

forRoot에서 forRootAsync로 바꾼 이유가 있다.

 

Nest.js 웹 어플리케이션이 bootstraping 될 때 DB의 동적 구성을 허용할 수 있어야 하는데 
TypeOrmConfigService가 동적 구성 되지 않고 타이밍을 못맞춰 설정이 안 될 경우가 있으므로
forRootAsync를 사용함으로써 해결하고 있는 모습이다. 

 

아직까진 .env를 사용하지 않았는데 이제 사용해볼거임

 

.env 파일 생성

 

.env

DATABASE_HOST='localhost'
DATABASE_PORT=3306
DATABASE_USERNAME='root'
DATABASE_PASSWORD='qwer1234'
DATABASE_NAME='nest_prac'

.env 세팅을 했으니 configuration을 해주자

 

app.module.ts

ConfigModule.forRoot({ isGlobal: true }),

 

사용방법

typeorm.config.service.ts

constructor(private readonly configService: ConfigService) {}

board.service에서 DI 했을 때 처럼 생성자를 통해 DI 해준다.

 

process.env.DATABASE_HOST

예전에는 이런식으로 썼다면

this.configService.get<string>('DATABASE_HOST')

이제 이런식으로 사용하면 된다. 

 

결과적으로 이렇게 작성해주면 된다.

 

** 참고로 위에서 DATABASE_NAME으로 명시한 DB는 미리 만들어놔야 한다.

테이블은 TypeORM이 sync해서 자동으로 생성해주지만 DB는 아니므로 꼭! 직접 만들어야 에러없이 정상 작동된다.

728x90