-
[고농축 백엔드 코스Quiz6]프론트엔드와 API 연동하기 - 문자 & 이메일 보내기프로젝트/고농축 백엔드 코스 2023. 8. 1. 18:13

quiz6/frontend/login
더보기<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>로그인/회원가입</title> <link rel="stylesheet" href="./index.css" /> <script src="./index.js"></script> <script src="./signup.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <!-- 전체 컨테이너 --> <div class="Container"> <!-- 여기서부터 회원가입 모달창 --> <div id="ModalContainer" onclick="CloseModal()"></div> <div id="SignupModalWrapper"> <div class="SignupTitle">회원가입</div> <div class="SignupInputWrapper"> <span class="SignupInputName">이름</span> <input id="SignupName" class="SignupInput" type="text" placeholder="이름을 입력해주세요" /> </div> <div class="SignupInputWrapper"> <span class="SignupInputName">주민등록번호</span> <div style="display: flex; align-items: center"> <input id="SignupPersonal" style="width: 40%; text-align: center" class="SignupInput" type="text" maxlength="6" /> <span style=" text-align: center; color: #fff; padding: 0 5px 0 5px; font-size: 20px; " >- </span> <input style="width: 40%; text-align: center" class="SignupInput" type="password" maxlength="7" /> </div> </div> <div class="SignupInputWrapper"> <span class="SignupInputName">핸드폰 번호</span> <div style=" display: flex; justify-content: space-between; padding-bottom: 20px; " > <div style="display: flex"> <input id="PhoneNumber01" class="SignupInput" type="text" maxlength="3" value="010" readonly /><span class="PhoneSlash">-</span ><input id="PhoneNumber02" class="SignupInput" type="text" maxlength="4" /><span class="PhoneSlash">-</span ><input id="PhoneNumber03" class="SignupInput" type="text" maxlength="4" /> </div> <span class="NumberVailidationBtn" onclick="getValidationNumber()" >인증 번호 전송</span > </div> <div id="ValidationInputWrapper" style="display: none; align-items: center" > <input id="TokenInput" class="ValidationInput" type="text" placeholder="전송 받은 인증번호를 입력해주세요" /> <span id="LimitTime">1:00</span> <div class="NumberVailidationBtn" onclick="submitToken()"> 인증 완료 </div> </div> </div> <div class="SignupInputWrapper"> <span class="SignupInputName">좋아하는 사이트</span> <input id="SignupPrefer" class="SignupInput" type="text" placeholder="좋아하는 사이트를 입력해주세요" /> </div> <div class="SignupInputWrapper"> <span class="SignupInputName">이메일</span> <input id="SignupEmail" class="SignupInput" type="text" placeholder="이메일을 입력해주세요" /> </div> <div class="SignupInputWrapper"> <span class="SignupInputName">비밀번호</span> <input id="SignupPwd" class="SignupInput" type="password" placeholder="비밀번호를 입력해주세요" /> </div> <div class="ButtonWrapper"> <div class="Signup" onclick="submitSignup()">회원 가입</div> </div> </div> <!-- 여기까지가 회원가입 모달창 --> <!-- 본 컨텐츠 --> <div class="Wrapper"> <div class="LogoWrapper"> <img class="LogoImg" src="../img/starbucks.png" /> <div class="LogoTitle">CodeBucks</div> <a href="../menu/index.html" class="Menu_Button"> 메뉴 바로가기</a> </div> <div id="SocialLoginGoogle"> <img class="SocialLoginButtonImg" src="../img/google.png" /> <div class="SocialLoginButtonTitle">구글로 로그인</div> </div> <div id="SocialLoginNaver"> <img class="SocialLoginButtonImg" src="../img/naver.png" /> <div class="SocialLoginButtonTitle">네이버로 로그인</div> </div> <div id="SocialLoginKakao"> <img class="SocialLoginButtonImg" src="../img/kakao.png" /> <div class="SocialLoginButtonTitle">카카오톡으로 로그인</div> </div> <div id="SocialLoginFacebook"> <img class="SocialLoginButtonImg" src="../img/facebook.png" /> <div class="SocialLoginButtonTitle">페이스북으로 로그인</div> </div> <div class="SignupWrapper"> 아직 회원이 아니신가요? <span class="SignupButton" onclick="OpenModal()">가입 하기</span> </div> </div> </div> </body> </html>quiz/backend/index.js
더보기import express from "express"; import { sendTokenToSMS, checkPhone, getToken } from "./phone.js"; import swaggerUi from "swagger-ui-express"; import swaggerJsdoc from "swagger-jsdoc"; import { options } from "./swagger/config.js"; import cors from "cors"; import "dotenv/config"; import nodemailer from "nodemailer"; import { format } from "date-fns"; const app = express(); app.use(express.json()); //.use는 get&post 모두에서 작동한다 app.use(cors()); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerJsdoc(options))); app.post("/tokens/phone", function (req, res) { // 들어온 값 확인하기 // postman으로 요청 보낼 때 {"<key>":"값"}을 해줘야함 // key = req.body.<key> 로 설정하고. const phoneNo = req.body.number; // 1. 휴대폰 번호 자리수 맞는지 확인하기 const isValid = checkPhone(phoneNo); if (isValid === false) return; // 2. 핸드폰 토큰 6자리 만들기 const token = getToken(); // 3. 핸드폰 번호에 토큰 전송하기 sendTokenToSMS(phoneNo, token); res.send(phoneNo); }); app.post("/email", function (req, res) { const userInfo = req.body.userInfo; // 1. 회원이 입력한 정보 받아오기 const sendEmailFormat = joinMailTemplate(userInfo); // 2a. 회원 이메일 받아오기 const userEmail = userInfo.email; // // 2b. 회원 이메일 유효한지 확인하기 const isValid = checkEmail(userEmail); if (isValid === false) { return; } // 2. 회원이 받아온 정보를 이메일로 보내기 sendWelcomeEmail(userEmail, sendEmailFormat); console.log("메일 전송완료"); }); const checkEmail = (email) => { // 1. 이메일이 정상인지 확인 (a. 존재여부, b. "@"존재여부) // console.log("email : ", email); if (!email || !email.includes("@")) { console.log("이메일을 제대로 입력해주세요 ! "); return false; } else { return true; } }; function joinMailTemplate(data) { const today = new Date(); const formattedDate = format(today, "yyyy-MM-dd"); const myTemplate = ` <html> <body> <div style="display : flex; flex-direction:column; align-items:center"> <div style="width : 500px;"> <h1>${data.name}님 가입을 환영합니다!!!</h1> <hr /> <div>이름 : ${data.name}</div> <div>전화번호 : ${data.phoneNo}</div> <div>좋아하는 사이트 : ${data.prefer}</div> <div style="color:red";>가입일 : ${formattedDate}</div> </div> </div> </body> </html> `; return myTemplate; } async function sendWelcomeEmail(emailAddr, welcomeTemplate) { const transporter = nodemailer.createTransport({ service: "gmail", auth: { user: process.env.MY_EMAIL, pass: process.env.GOOGLE_PW, // Google에서 제공한 2차비밀번호 => email / windows computer }, }); const res = await transporter.sendMail({ from: process.env.MY_EMAIL, to: emailAddr, subject: " === 메일 전송 테스트 === ", html: welcomeTemplate, }); } app.listen(4000);quiz6/frontend/login/index.js
더보기const OpenModal = () => { let ModalBackground = document.getElementById("ModalContainer"); let Modal = document.getElementById("SignupModalWrapper"); ModalBackground.style.display = "flex"; Modal.style.display = "flex"; }; const CloseModal = () => { let ModalBackground = document.getElementById("ModalContainer"); let Modal = document.getElementById("SignupModalWrapper"); Modal.style.display = "none"; ModalBackground.style.display = "none"; };quiz6/frontend/login/signup.js
더보기// 휴대폰 인증 토큰 전송하기 const getValidationNumber = async () => { document.querySelector("#ValidationInputWrapper").style.display = "flex"; phoneNo = validatePhoneNo(); // 파라미터로 getNumber()에 넘기기 await getNumber(phoneNo); console.log("인증 번호 전송"); }; // 휴대폰 번호 받기 const validatePhoneNo = () => { // html에 있는 핸드폰 번호를 하나의 번호로 받기 const phoneNo = document.querySelector("#PhoneNumber01").value + document.querySelector("#PhoneNumber02").value + document.querySelector("#PhoneNumber03").value; return phoneNo; }; // 회원 가입 API 요청 const submitSignup = async () => { const userInfoArray = { name: document.querySelector("#SignupName").value, personal: document.querySelector("#SignupPersonal").value, phoneNo: validatePhoneNo(), prefer: document.querySelector("#SignupPrefer").value, password: document.querySelector("#SignupPwd").value, email: document.querySelector("#SignupEmail").value, }; await getUserInfo(userInfoArray); }; const getNumber = (phoneNo) => { return axios.post("http://localhost:4000/tokens/phone", { number: phoneNo }); }; const getUserInfo = (userInfoArray) => { return axios.post("http://localhost:4000/email", { userInfo: userInfoArray, }); };backend/index.js의 파일의 checkEmail(), joinMailTemplate(), sendWelcomEmail()을 너무 분리시키고 싶은데 분리시킬 때마다 export 에러가 발생한다. 너무 시간을 많이 잡아먹어서 일단 스킵한다.
에러 :
Uncaught SyntaxError: Unexpected token 'export'
Uncaught ReferenceError: "함수명" is not defined at HTMLSpanElement.onclick
해결법을 찾아서 export를 붙여주면 어떤 에러가 나고,
안붙여주면 다른 에러가 나고.. 포기 ㅠㅠ
반응형'프로젝트 > 고농축 백엔드 코스' 카테고리의 다른 글
[고농축 백엔드 코스Quiz12]Nest.js 프로젝트 생성 / Starbucks 메뉴 조회 API 만들기 (0) 2023.08.04 [고농축 백엔드 코스Quiz5]프론트엔드와 API 연동하기 - /starbucks (0) 2023.07.30 [고농축 백엔드 코스Quiz5]Rest-API를 GrapQL-API로 변경하기 (0) 2023.07.27 [고농축 백엔드 코스Quiz4] API 명세서 만들기(Swagger) (0) 2023.07.26 [고농축 백엔드 코스Quiz4]Node.js로 회원 목록 조회 API 만들기 (0) 2023.07.26