본문 바로가기

node.js - async-await / axios 활용 문자&메일 발송 / 환경변수 본문

개발/node.js

node.js - async-await / axios 활용 문자&메일 발송 / 환경변수

자전하는명왕성 2023. 1. 17. 00:28

async-await

 

async-await를 이해하기 위해선 동기와 비동기 개념을 이해해야 한다.

동기 : 등록이 될 때까지 기다림 / 서버 컴퓨터가 작업이 끝날 때까지 기다리는 통신

비동기 : 요청들이 서로 기다릴 필요 없을 때 사용 / 동시에 여러 일을 할 때 / 서버 컴퓨터가 작업이 끝날 때까지 기다리지 않는 통신

=> axios 와 같은 API 관련 기능들은 '비동기'가 기본값

 

vscode 내에서 비동기

// 비동기 통신
// 비동기로 실행되기 때문에 생기는 Promise

const data = axios.get(url - / 중략 / ) // API정보를 받아오기 전에 저장
console.log(data) 


// 비동기 통신 (async / await)
// async : 함수 앞 / await 동기 작동(API)을 원하는 위치

async function () {
	const data = await axios.get(url - / 중략 / )
	console.log(data) // 정상적인 API정보 저장 가능
}

// 함수선언식으로 사용하는 법
const fetchSync = async() => {
    const result = await axios.get("https://koreanjson.com/posts/1");
    console.log("비동기 방식 : ", result); // 제대로된 결과 => {title: "...."}
    console.log("비동기 방식 : ", result.data.title)
}

 

이때 async 와 await의 위치에 집중할 필요가 있다.

() 을 기준으로, function이 존재하면 그 앞, 없다면 ()앞에 존재하면 된다.

// 함수표현식에서의 위치
'async' function () { 
	const data = 'await' axios.get(url - / 중략 / )
}

// 함수선언식에서의 위치
const 함수이름 = 'async'() => {
    const data = 'await' axios.get(url - / 중략 /)
}
await 의 경우, '비동기' 작동을 하고자 원하는 기능 앞에 위치시켜주면 된다.

 

 

coolSMS

coolSMS 는 rest API를 활용하여 문자보내는 사이트다.

해당 기능을 통해 문자보내는 방식

// phone.js 
// coolsms 양식
import coolsms from 'coolsms-node-sdk' 
const mysms = coolsms.default

// 중략 // 
// 휴대폰 번호 길이 검증 & 토큰 생성 함수
// 이때 SMS_KEY & SMS_SECRET & SMS_SENDER 는 환경변수 .env 에 보관
// anync & await 사용

export async function sendTokenToSMS (myphone, result) {
    const SMS_KEY = process.env.SMS_KEY 		// SMS_KEY API키
    const SMS_SECRET = process.env.SMS_SECRET	// SMS_SECRET API키 비밀번호
    const SMS_SENDER = process.env.SMS_SENDER	// SMS_SENDER 보내는 이
    const messageService = new mysms(SMS_KEY,SMS_SECRET) // 양식
    const res = await messageService.sendOne({			 // 양식
        to: myphone,									 // 양식
        from:SMS_SENDER,
        text: `안녕하세요? 인증번호는 ${result}입니다.`
    })
    console.log(res)
}

// index.js
import express from "express"; // 요즘 방식 -> module 방식
import { checkPhone, getToken, sendTokenToSMS } from "./phone.js"; // export 가져오기
import "dotenv/config"

function zzz(){ 	// 인증하기 버튼 누를 시 실행되는 함수
	const myPhone = document.getElementById('myPhone').value

	axios.post("http://localhost:3000/tokens/phone", {
    	qqq : myPhone		// qqq 에 입력한 번호 저장
        }).then((res) => {
        	console.log(res.data)
            document.getElementById('result').innerText = res.data
	})
}

app.post("/tokens/phone", function (req, res) {
    console.log(req);
    let myPhone = req.body.qqq;				// qqq = input.value
    const isValid = checkPhone(myPhone);	
    if (isValid == false) return;			// 검증 함수 
    const myToken = getToken();
	sendTokenToSMS(myPhone, myToken);

    res.send("인증 완료!");
});

app.listen(3000);

 

데이터 흐름을 기억하면 좋을 것 같다.

  • 브라우저(번호 입력) =>
  • zzz함수 실행(API, req.body.qqq 에 번호 저장) => // axios 로 전송
  • express 로 받음 // app.post 실행 => 문자 전송

** 이때 API 키와 API Secret 은 따로 '.env' 환경변수에 저장해둔 뒤 따로 관리한다.

결과물

 

nodemailer

nodemailer 는 메일을 rest API를 활용하여 문자보내는 사이트다.

해당 기능을 통해 이메일 보내는 방식

// email.js
import { getToday } from "./utils.js" 	// 가입일을 알리기 위한 함수
import nodemailer from 'nodemailer'		// nodemailer 설치

// 이메일 검증 함수 생략 //

// 템플릿 만드는 함수 생략 // 

// 템플릿 메일로 보내는 함수
export async function sendTemplateToEmail(email, template){	// async
    const EMAIL_ID = process.env.EMAIL_ID					// email_id
    const EMAIL_PW = process.env.EMAIL_PW					// 2차 비밀번호
    
    const transporter = nodemailer.createTransport({

        service : "gmail",
        auth : {
            user : EMAIL_ID,
            pass : EMAIL_PW
        }
    })

const res = await transporter.sendMail({ // nodemailer 양식
        from: "// 보내고자 하는 이메일 //",
        to : email,						// 양식
        subject : "가입을 축하합니당",
        html : template
    })
console.log(res)
    
// index.js    
// 회원등록 API
// {name,age,school,email} req.body.~에서 받아옴
app.post("/users", function(req, res){
    // const name = req.body.name
    // const age = req.body.age
    // const school = req.body.school
    // const email = req.body.email
    const {name, age, school, email} = req.body // 구조분해할당

    const isValid = checkEmail(email) // 검증
    if(isValid == false) return
    
    let template = makeTemplate(name,age,school) // 템플릿 함수
    
    // 3. 이메일에 가입환영 템플릿 전송하기
    sendTemplateToEmail(email, template) // 전송 함수
    
    res.send("가입완료")					// 출력 메시지
    console.log(`${email}로, ${template}전달하였씁니당`)
})
app.listen(3000);

 

결과물 (포스트맨으로 데이터 입력 & 메일)

환경변수 .env

앞서 얘기한 환경변수에 대해 얘기를 해보자.

API 키와 API 비밀번호는 중요정보기 때문에 따로 취급할 필요가 있다.

이를 위해 생성한 파일이 '.env'인데, 이는 "환경변수"의 약자로 키값을 저장할 때 사용한다.

// .env

SMS_KEY = -----
SMS_SECRET = -----------------
SMS_SENDER = -----
EMAIL_ID = ----@gmail.com
EMAIL_PW = --------

해당 데이터는 위와 같이 변수에 할당할 수 있으며, 

dotenv 을 설치한 뒤 import 'dotenv/config' 를 지정하여 변수명으로 불러올 수 있다. (이때 import는 최상위 파일)

이후 .gitignore 에 .env 을 설치하면 git에 올리지 않으면서 해당 파일을 안전하게 저장할 수 있다.

 

6일차 과제 : 브라우저에서 데이터를 받아와 해당 데이터로 문자 & 메일을 전송하는 기능 구현

// 문자 rest API 구현

// 1. 브라우저 입력 단계 // signup.js
const getValidationNumber = async () => {
    document.querySelector("#ValidationInputWrapper").style.display = "flex";
    console.log("인증 번호 전송");
    const phone1 = document.querySelector("#PhoneNumber01").value;
    const phone2 = document.querySelector("#PhoneNumber02").value;
    const phone3 = document.querySelector("#PhoneNumber03").value;
    console.log(phone1 + phone2 + phone3);
    let phoneNumber = phone1 + phone2 + phone3; // 휴대폰 번호
    axios
        .post("http://localhost:3000/tokens/phone", { phoneNumber }) // 휴대폰 번호 post
        .then((res) => {
            console.log(res, "휴대폰 토큰 전송됨");
        });
};



// 2. 문자 메시지 API// index.js
import express from "express";
import {checkPhone,getToken,sendTokenToSMS} from "./phone.js"
const app = express(); 
app.use(cors())
app.use(express.json())

app.post("/tokens/phone", function (req, res) {
    console.log(req);
    
    let {phoneNumber} = req.body

    const isValid = checkPhone(phoneNumber);
    if (isValid == false) res.send("인증실패")

    const myToken = getToken();

    sendTokenToSMS(phoneNumber, myToken);

    res.send("인증 완료!");
});    


// 3. 함수 및 비동기 함수 실행 phone.js
import 'dotenv/config'
import coolsms from 'coolsms-node-sdk'
const mysms = coolsms.default

// 타 기능 함수 생략 //

export async function sendTokenToSMS (myphone, result) {
    const SMS_KEY = process.env.SMS_KEY
    const SMS_SECRET = process.env.SMS_SECRET
    const SMS_SENDER = process.env.SMS_SENDER
    const messageService = new mysms(SMS_KEY,SMS_SECRET)
    const res = await messageService.sendOne({
        to: myphone,
        from:SMS_SENDER,
        text: `안녕하세요? 인증번호는 ${result}입니다.`
    })
    console.log(res)
}

 

// 1. 브라우저 입력 / signup.js

// 회원 가입 API 요청
const submitSignup = async () => {
    const SignupName = document.getElementById("SignupName").value
    const SignupPersonal = document.querySelector("#SignupPersonal").value
    const SignupPrefer = document.querySelector("#SignupPrefer").value
    const SignupEmail= document.querySelector("#SignupEmail").value
    const SignupPwd = document.querySelector("#SignupPwd").value
    const SignupPhone =
            document.querySelector("#PhoneNumber01").value -
            document.querySelector("#PhoneNumber02").value -
            document.querySelector("#PhoneNumber03").value
    
    axios.post("http://localhost:3000/signup", {SignupName,SignupPersonal,SignupPrefer,SignupEmail,SignupPwd,SignupPhone}).then((res) => {
        console.log(res, "회원가입 데이터 전송됨"); // 데이터 객체 전송
    });
};

// 2. rest API 실행

app.post("/signup", function(req, res){
 
    const {SignupName,SignupPersonal,SignupPrefer,SignupEmail,SignupPwd,SignupPhone} = req.body // 구조분해할당

    const isValid = checkEmail(SignupEmail)
    if(isValid == false) return
    
    let template = makeTemplate(SignupName,SignupPhone,SignupPrefer)
    
    sendTemplateToEmail(SignupEmail, template)
    
    res.send("가입완료")
    console.log(`${SignupEmail}로, ${template}전달하였씁니당`)
})

app.listen(3000);

//  3. 메일 발송


export async function sendTemplateToEmail(email, template){
    const EMAIL_ID = process.env.EMAIL_ID
    const EMAIL_PW = process.env.EMAIL_PW
    
    const transporter = nodemailer.createTransport({

        service : "gmail",
        auth : {
            user : EMAIL_ID,
            pass : EMAIL_PW
        }
    })

    const res = await transporter.sendMail({
        from: "-----@gmail.com",
        to : email,
        subject : "가입을 축하합니당",
        html : template
    })
    console.log(res)

Comments