ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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

    댓글

Designed by Tistory.