Skip to content

10. Configurations


1. 설정 파일 만들기

소스 코드 안에서 어떠한 코드는 개발 환경(Dev)이나 운영 환경(Prod)에 따라서 다르게 넣어줘야 할 때가 있다. 또한 남들에게 노출되지 않아야 하는 코드도 있다. 이러한 코드를 위해 설정 파일을 따로 만들어서 관리해야 한다.


설정에 필요한 모듈을 설치한다.


npm install --save config


src 디렉터리와 같은 레벨에 config 디렉터리를 생성하고, default.yaml, development.yaml, production.yaml 파일을 생성한다.


mkdir config
touch config/default.yaml config/development.yaml config/production.yaml


default.yaml 파일에는 개발 환경이나 운영 환경 모두에서 사용되는 기본 설정을 작성한다. development.yaml 파일에는 개발 환경에 사용되는 설정을 작성한다. production.yaml 파일에는 운영 환경에 사용되는 설정을 작성한다.


server:
  port: 3000

db:
  type: "postgres"
  port: 5432
  database: "board-app"

jwt:
  expiresIn: 3600
db:
  host: "localhost"
  username: "postgres"
  password: "postgres"
  synchronize: true

jwt:
  secret: "Secret1234"
db:
  synchronize: false


2. 설정 파일 적용하기

설정 파일을 생성하면 어느 파일에서든지 다음과 같이 config 모듈을 가져와서 사용하면 된다.


import * as config from "config";
import { Logger } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import * as config from "config";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const serverConfig = config.get("server");
  const port = serverConfig.port;

  await app.listen(port);
  Logger.log(`Application running on port ${port}`);
}
bootstrap();
import { TypeOrmModuleOptions } from "@nestjs/typeorm";
import * as config from "config";

const dbConfig = config.get("db");

export const typeOrmConfig: TypeOrmModuleOptions = {
  type: dbConfig.type,
  host: process.env.RDS_HOSTNAME || dbConfig.host,
  port: process.env.RDS_PORT || dbConfig.port,
  username: process.env.RDS_USERNAME || dbConfig.username,
  password: process.env.RDS_PASSWORD || dbConfig.password,
  database: process.env.RDS_DB_NAME || dbConfig.database,
  autoLoadEntities: true,
  synchronize: dbConfig.synchronize,
};
import { Module } from "@nestjs/common";
import { JwtModule } from "@nestjs/jwt";
import { PassportModule } from "@nestjs/passport";
import { TypeOrmModule } from "@nestjs/typeorm";
import { AuthController } from "./auth.controller";
import { AuthService } from "./auth.service";
import { JwtStrategy } from "./jwt.strategy";
import { User } from "./user.entity";
import * as config from "config";

const jwtConfig = config.get("jwt");

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: "jwt" }),
    JwtModule.register({
      secret: process.env.JWT_SECRET || jwtConfig.secret,
      signOptions: {
        expiresIn: jwtConfig.expiresIn,
      },
    }),
    TypeOrmModule.forFeature([User]),
  ],
  controllers: [AuthController],
  providers: [AuthService, JwtStrategy],
  exports: [JwtStrategy, PassportModule],
})
export class AuthModule {}
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { InjectRepository } from "@nestjs/typeorm";
import { ExtractJwt, Strategy } from "passport-jwt";
import { Repository } from "typeorm";
import { User } from "./user.entity";
import * as config from "config";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    @InjectRepository(User) private userRepository: Repository<User>
  ) {
    super({
      secretOrKey: process.env.JWT_SECRET || config.get("jwt.secret"),
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    });
  }

  async validate(payload: any) {
    const { username } = payload;
    const user: User = await this.userRepository.findOneBy({ username });

    if (!user) {
      throw new UnauthorizedException();
    }

    return user;
  }
}

References