-
230102월_공부일지> Backend/NestJS 2023. 1. 2. 09:21
1. NestJS에서 제공하는 Config 패키지
=> 이전까지는 dotenv패키지를 직접 사용했는데, 이젠, nestJS에서 제공되는 패키지를 사용할 예정
=> cmd: npm i --save @nestjs/config
=>
//dotenv import {ConfigModule} from "@nestjs/config"; import emailConfig from "./config/emailConfig"; import { validationSchema } from './config/validationSchema'; @Module({ // Nest에서 제공되는 Config 패키지 // forRoot 매서드는 Dynamic Module을 리턴하는 정적 메서드 imports: [UsersModule, EmailModule, ConfigModule.forRoot({ envFilePath: [`${__dirname}/config/env/.${process.env.NODE_ENV}.env`], load: [emailConfig], // load 속성을 통해 앞서 구성해둔 configFactory 지정 isGlobal: true, // 전역 모듈로 사용 validationSchema // 환경변수의 값에 대한 유효성 검사를 수행하도록 joi를 이용해 유효성 검사 객체를 작성 })], controllers: [ApiController, AppController], providers: [AppService], }) export class AppModule { }
=> NestJS가 제공하는 ConfigModule은 dotenv 파일에서 읽어온 환경 변수 값을 가져오는 프로바이더인 ConfigService가 있고, 이를 사용하기 위해서는 원하는 컴포넌트에 주입해서 사용하면 됨.
export class AppController { constructor( private readonly appService: AppService, private readonly emailService: EmailService, private readonly configService: ConfigService) { } @Get('/db-host-config') getDatabaseHostFromConfigService(): string { return this.configService.get('DATABASE_HOST') } ... 하략 ...
2. 유저 서비스에 환경 변수 구성하기
=> cmd : npm i @nestjs/config
=> cmd : npm i joi
=> 기존에 src/env 디렉토리 내에 있던 파일들을 src/config/env 디렉토리를 생성하고, 해당 디렉토리로 이동
=> 추가적으로 각 .env파일에 해당 내용 추가
EMAIL_SERVICE=Gmail EMAIL_AUTH_USER= 지메일 이메일 주소 EMAIL_AUTH_PASSWORD= 지메일 비번 EMAIL_BASE_URL= http://localhost:3000
3. 커스텀 Config 파일 작성
=> 모든 환경 변수가 .env 파일에 선언되어있지만, EmailConfig와 같이 의미있는 단위로 묶어서 처리하고 싶을 경우 @nestjs/config 패키지에서 제공하는 ConfigModule를 사용.
=>
import { registerAs } from "@nestjs/config"; export default registerAs( 'email ', () => ({ service: process.env.EMAIL_SERVICE, auth: { user: process.env.EMAIL_AUTH_USER, pass: process.env.EMAIL_AUTH_PASSWORD }, baseUrl: process.env.EMAIL_BASE_URL })) // 설명: @nestjs/config 패키지에서 제공하는 registerAs 함수의 선언을 보면, // 첫번째 인자로는 토큰을 문자열로 받고, 두번째 인수로는 ConfigFactory 함수를 상속하는 타입 TFacotry의 함수를 받아서 TFacotry의 && ConfigFacotryKeyHost를 합친 타입의 함수를 리턴함. // emailConfig.ts를 설명하면, email 이라는 토큰으로 ConfigFactory 를 등록할 수있는 함수라고 이해할 것.
4. 동적 ConfigModule 등록
=> NestJS 기본 빌드 옵션은 .ts 파일 외에 asset은 제외하도록 되어 있기 때문에, .env 파일을 out 디렉토리에 복사할 수 있도록, NEST-CLI.JSON에서 옵션을 바꿔줘야함.
... 생략 "compilerOptions": { "assets": [ { "include": "./config/env/*.env", "outDir": "./dist" } ] }
=> app.module.ts 에 validationSchema를 (./config/validationSchema) 에 생성
validationSchema // 환경변수의 값에 대한 유효성 검사를 수행하도록 joi를 이용해 유효성 검사 객체를 작성
import * as Joi from 'joi'; export const validationSchema = Joi.object({ EMAIL_SERVICE: Joi.string().required(), EMAIL_AUTH_USER: Joi.string().required(), EMAIL_AUTH_PASSWORD: Joi.string().required(), EMAIL_BASE_URL: Joi.string().required().uri(), })
=> .gitignore 에 env 파일 안올라가게 설정 ( 깃에 올리면 안되는 환경 변수 )
# local env files *.env .env.local .env.*.local Env.json
=> 가끔 깃에 올리면 안되는 환경 변수들도 있는데, 이런 변수들은 Nest가 구동되기 전에 서버가 프로비저닝되는 과정에서 다른 비밀번호 관리 시스템을 읽어와서 소스 코드 내의 .env 파일을 수정하도록 하는 방법을 쓰거나, 미리 컴파일 된 dist 파일을 다른 저장소에서 가져와서 수정하여 구동하는 방법을 사용해야 함.
=> 이제, emailConfig를 우리가 사용하려고 하는 곳에 주입받아 사용 할 수 있다.
import {Injectable, Inject} from '@nestjs/common'; import Mail = require('nodemailer/lib/mailer'); import * as nodemailer from 'nodemailer' import * as process from "process"; import {ConfigType} from "@nestjs/config"; import emailConfig from "../config/emailConfig"; interface EmailOptions { to: string, subject: string, html: string } @Injectable() export class EmailService { private transporter: Mail; // before // constructor() { // this.transporter = nodemailer.createTransport({ // service: 'gmail', // auth: { // // user: 'G-MAIL 이메일 주소', // // pass: 'G-MAIL 이메일 비번 > 2차 비번' // user: process.env.GOOGLE_EMAIL, // pass: process.env.GOOGLE_PW // // nodemailer는 간단한 이메일 전송 테스트만을 위해 작성되었기 때문에, 2단계 인증 활성화 및 앱 비밀번호를 진행해야됨 // } // }) // } // after constructor( @Inject(emailConfig.KEY) private config: ConfigType<typeof emailConfig> // 주입받을 떄는 @Inject decorator의 토큰을 앞서 만든 ConfigFactory의 KEY 인 'email' 문자 열로 넣어주기 ) { this.transporter = nodemailer.createTransport({ service: config.service, auth: { user: config.auth.user, pass: config.auth.pass } }) } ß async sendMemberJoinVerification(emailAddress: string, signupVerifyToken: string) { const baseUrl = this.config.baseUrl // .env파일에 있는 값들을 사용 const url = `${baseUrl}/users/email-verify?signupVerifyToken=${signupVerifyToken}`; const mailOptions: EmailOptions = { to: emailAddress, subject: '가입인증 메일', html: ` 가입확인 버튼을 누르시면 가입인증이 완료 됩니다. <br/> <form action="${url}" method="POST"> <button>가입 확인 버튼</button></form> ` } return await this.transporter.sendMail(mailOptions); } }
'> Backend > NestJS' 카테고리의 다른 글
230105목_공부일지 (0) 2023.01.05 20221229목_공부일지 (0) 2022.12.30 221228수_공부일지 (0) 2022.12.29 20221227화_공부 일지 (0) 2022.12.28 20221222Thu_공부 일지 (0) 2022.12.23