(이 강의부터 John Ahn님이 제공하시는 보일러 플레이트 틀 바탕으로 코드를 수정한 뒤 진행됨)
요즘 회원가입 시에는 휴대번호나 이메일 인증은 필수이기 때문에 노드 리액트 기초 강의를 끝내고 먼저 한 일은 이메일 인증이었다.
먼저, 이메일 인증과 관련해서 찾아보던 중 nodemailer라는 것을 알게 되었고, 이 모듈을 사용하기로 했다.
Nodemailer는 쉽게 이메일을 보낼 수 있도록 하는 Node.js 애플리케이션용 모듈이다.
먼저 터미널 창에 npm install nodemailer dotenv --save를 하여 다운받는다.
이메일을 보내는 사람의 이메일 주소와 비밀번호가 코드에 포함되는데, dotenv를 사용하여 이를 따로 관리할 수 있다.
server 폴더 안에 mail.js 파일을 생성하고 다음 코드를 작성한다.
//mail.js
require('dotenv').config();
const mailer = require("nodemailer");
const { Hello } = require("./hello_template");
const getEmailData = (to, authCode) => {
data = {
from: "BabyAngel",
to,
subject: "Hello",
html: Hello(authCode)
}
return data;
}
const sendEmail = (to, authCode) => {
const smtpTransport = mailer.createTransport({
service: "Gmail",
auth: {
user: process.env.NODEMAILER_USER,//보내는 사람 이메일
pass: process.env.NODEMAILER_PASS //비밀번호
}
})
const mail = getEmailData(to, authCode)
smtpTransport.sendMail(mail, function(error, response) {
if(error) {
console.log(error)
} else {
console.log("email sent successfully")
}
smtpTransport.close();
})
}
module.exports = { sendEmail }
그리고 마찬가지로 server 폴더 안에 hello_template.js 파일을 생성하여 사용자에게 보낼 이메일 형식을 html 형식으로 작성한다.
const Hello = data => {
return `
<!DOCTYPE html>
<html style="margin: 0; padding: 0;">
<head>
<title>이메일 인증하기</title>
</head>
<body style="margin: 0; padding: 0; font-size:15px;">
<div>인증번호는 ${data} 입니다.</div>
</body>
</html>
`
}
module.exports = { Hello }
mail.js에서 process.env.NODEMAILER_USER와 process.env.NODEMAILER_PASS를 따로 관리해주는 .env 파일을 root directory에 생성한다. 만약 코드를 git에 올린다면 .env파일은 개인정보를 담고 있기 때문에 .gitignore에 추가해서 git에 올라가지 않게 해줘야 한다.
// .env
NODEMAILER_USER = "이메일을 보내는 사람의 이메일 주소"
NODEMAILER_PASS = "이메일을 보내는 사람의 비밀번호"
각 NODEMAILER_USER와 NODEMAILER_PASS에는 실제 본인 이메일과 비밀번호를 입력하면 된다.
그런 다음 server>routes>users.js에 인증코드를 발송하는 sendEmail api를 작성한다.
//users.js
const { sendEmail } = require('../mail');
router.post('/sendEmail', (req, res) => {
sendEmail(req.body.email, req.body.auth)
return res.status(200).json({
success: true
})
})
이제 백엔드 부분은 완성 되었고 프론트에서 인증버튼을 눌렀을 때 백엔드로 요청을 보내는 코드를 작성하면 되겠다.
(이름, 비밀번호, 비밀번호 인증 부분의 코드는 앞에서 다뤘기 때문에 다음 코드에서 생략되어 있다.)
import React, { useState } from 'react'
import { useDispatch } from 'react-redux';
import { registerUser } from '../../../_actions/user_action';
import { withRouter } from 'react-router-dom';
import axios from 'axios';
var state = {
createdAuthCode: "",
authCodeCheck: false
}
function RegisterPage(props) {
const dispatch = useDispatch()
const [Email, setEmail] = useState("")
const [AuthCode, setAuthCode] = useState("")
const onEmailHandler = (event) => {
setEmail(event.currentTarget.value)
}
const onAuthCodeHandler = (event) => {
setAuthCode(event.currentTarget.value)
}
const onNameHandler = (event) => {
setName(event.currentTarget.value)
}
const onSendMailHandler = (event) => {
event.preventDefault();
state.createdAuthCode = Math.random().toString(36).substr(2,6); //랜덤 문자열 6자리 생성
const dataToSubmit = {
email: Email,
auth: state.createdAuthCode
}
console.log('authCode = '+state.createdAuthCode)
axios.post("/api/users/sendEmail", dataToSubmit)
.then(response => {
alert("인증코드가 발송되었습니다.")
})
}
const onCheckHandler = (event) => {
event.preventDefault(); //page refresh 막아줌
console.log(state.createdAuthCode +" == "+AuthCode)
if(state.createdAuthCode == AuthCode) {
state.authCodeCheck = true;
alert("이메일 인증에 성공하셨습니다")
}
else {
state.authCodeCheck = false;
alert("인증 코드가 일치하지 않습니다.")
}
}
return (
<div style ={{ display: 'flex', justifyContent: 'center', alignItems: 'center',
width: '100%', height: '100vh' }}>
<div >
<form style={{ display: 'flex', flexDirection: 'column' }}
onSubmit={onSendMailHandler}>
<h2>RegisterPage</h2>
<br/>
<label>Email</label>
<div>
<input type="email" value={Email} onChange={onEmailHandler} required/>
<button type="submit">
send code
</button>
</div>
</form>
<form style={{ display: 'flex', flexDirection: 'column' }}
onSubmit={onCheckHandler}
>
<label>Authentication Code</label>
<div>
<input type="text" value={AuthCode} onChange={onAuthCodeHandler} required/>
<button type="submit">
check
</button>
</div>
</form>
</div>
</div>
)
}
export default withRouter(RegisterPage)
여기서 인증코드를 생성하는 부분은 Math.random().toString(36).substr(2,6) 이다.
Math.random().toString(36)을 하게 되면,
Math.random()은 0 이상 1 미만의 구간에서 근사적으로 균일한 부동소숫점 의사난수를 반환하고, toString()에 36을 넣어서 이 수를 36진수로 표현하게 된다.
그 결과 0.6feh4o7j... 처럼 나오게 되는데 소숫점 아래 6자리만 사용할 것이기 때문에 substr(2, 6)을 사용한 것이다.
이제 실행시키고 이메일을 입력해서 send code 버튼을 누르면 먼저 VSC 터미널 창에서 다음과 같이 로그가 찍혀 성공적으로 이메일이 전송되었음을 알 수 있다.
현재 이 글은 프로젝트가 모두 끝나고 작성하는 것이고, 아래 인증코드에 대한 이메일은 삭제했었는지 남아있지 않았다.. 하지만 nodemailer를 통해 성공적으로 이메일이 전송되어 온 것은 확인할 수 있다.
인증코드를 입력하고 check 버튼을 누르면 이메일 인증에 성공했음을 알려주는 alert창이 뜬다.
'Project > Web' 카테고리의 다른 글
[WhenWhatHow] 취미 공유 웹사이트 (0) | 2021.08.29 |
---|---|
[디지털 문방구] 게시글 목록 구현 (0) | 2021.08.18 |
[디지털 문방구] 게시글 작성 구현 (0) | 2021.08.06 |
[디지털 문방구] 프로젝트에 사용할 기술 소개 (0) | 2021.04.01 |