forRoot와 forRootAsync는 모두 모듈 초기화 시 필요한 옵션을 설정하는 함수입니다. forRootAsync는 옵션을 만드는 useFactory 함수를 async로 동작하도록 설정할 수 있습니다. 또는, 다른 의존성이 준비된 뒤에 초기화를 해야 하는 경우에도 사용됩니다.

ex) 데이터베이스 초기화

class="highlight">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// forRoot - 하드코딩된 설정
TypeOrmModule.forRoot({
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: 'password123',
})


// forRootAsync - 동적으로 설정 가져오기
TypeOrmModule.forRootAsync({
  inject: [ConfigService],
  useFactory: (configService: ConfigService) => ({
    type: 'mysql',
    host: configService.get('DB_HOST'),
    port: configService.get('DB_PORT'),
    username: configService.get('DB_USER'),
    password: configService.get('DB_PASS'),
  })
})

  • forRoot는 하드코딩된 옵션 객체를 그대로 넘겨줍니다.
  • forRootAsync는 옵션을 설정하기 위한 의존성인 ConfigService와, 옵션을 생성하는 팩토리 함수를 함께 넘겨줍니다. forRootAsync 함수를 사용해야 환경에 따라 다른 의존성을 사용할 수 있습니다.
  • useFactory 함수가 async가 아닐 때도 forRootAsync가 사용되는 이유는 inject 옵션을 통해 옵션을 가져오기 위해 필요한 configService와 같은 타 의존성을 주입할 수 있기 때문입니다.
class="highlight">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { readFile } from 'fs/promises';

TypeOrmModule.forRootAsync({
  inject: [ConfigService],
  useFactory: async (configService: ConfigService) => {
    // SSL 인증서 파일을 비동기로 읽기
    const sslCert = await readFile(
      configService.get('DB_SSL_CERT_PATH'), 
      'utf-8'
    );
    
    return {
      type: 'mysql',
      host: configService.get('DB_HOST'),
      port: configService.get('DB_PORT'),
      username: configService.get('DB_USER'),
      password: configService.get('DB_PASS'),
      ssl: {
        ca: sslCert,  // 파일에서 읽어온 인증서
      },
    };
  }
})
  • 파일을 읽는 비동기 작업이 필요한 경우 이렇게 useFactory에 async 키워드를 붙여 사용할 수 있습니다. 이렇게 하면 NestJS가 파일 읽기가 완료될 때까지 기다린 후 모듈을 초기화하므로, SSL 인증서가 제대로 로드된 상태로 DB 연결을 시작할 수 있습니다.

reference : https://docs.nestjs.com/graphql/quick-start#async-configuration