벌써 Bare Minimum을 마무리 하기로 한 31일이 일주일도 채 남지 않았다.
제목은 통일성있게 맞추려하다보니 <Findid, Findpw 구현(Oct 24, 2020 ~ Oct 25, 2020 회고)> 이라고 지었지만
저것만 한 것은 아니다.
Client와 Server의 통신이 바로바로 확인 되고 두 파트 모두 마무리가 되는 것을 확인해봐야 다음 기능 구현으로 넘어가기에도 수월하다는 것을 프로젝트 초반부터 깨달았고, 그러다보니 양 쪽 파트의 PR사항을 그날그날 코드 리뷰하느라 여기에도 코드 작업하는 시간 만큼 쓰이는 것 같다.
양 쪽 파트를 모두 코드리뷰하는 것은 정말 좋다. Client 파트를 맡아서 Server구현을 프로젝트가 진행되는 한 달간 못(?) 하게 되어 잊어버리면 어떡하지? 라는 걱정이 있었는데 코드리뷰를 통해 이 걱정은 할 필요가 없게 되었다.
또 블로그를 통해 각 기능에 대한 Client, Server 코드를 작성해보는 것도 도움이 많이 되고 있다.
아무튼 이번에 정리해 볼 기능은 Findid, Findpw 이다.
Login 컴포넌트에서 Findid, Findpw 컴포넌트 버튼을 누르면 각각의 컴포넌트로 리다이렉트가 된다.
※ SH님께서 (Oct 26, 2020) 에 지금까지 구현이 완성된 컴포넌트들의 CSS작업을 완료해주셨다. 정말.. 갓SH님..
1. Findid 컴포넌트 구현 - (Oct 24, 2020) 회고
Findid 컴포넌트는 간단하다.
Client) 사용자가 githubID를 입력하고 제출하면 그걸 server의 findid API로 post 요청을 한다.
응답을 받으면 alert 창을 통해 찾은 Id인 email을 보여주고, 사용자가 확인 버튼을 누르면 login 페이지로 리다이렉트한다.
handleFindIdButton = () => (e) =>{
axios({
method:'post',
url: 'http://localhost:4000/users/login/findId',
data: {
github: this.github, //sate 변화가 필요없는 컴포넌트이기 때문에 state를 사용하지 않았고, 사용자가 input 태그에 입력한 e.target.value를 this.github에 넣어주었다.
}
})
.then((res) => {
if(res.data !==null){
alert('회원님의 email은 ' + res.data + ' 입니다. 로그인 페이지로 이동하시겠습니까?');
//확인 버튼을 누르면
this.props.history.push('/login');
}else{
alert('회원 정보가 존재하지 않습니다.');
}
})
.catch((err) => {
//status 400 Bad request
if (err.message === 'Request failed with status code 400') {
alert('올바른 Github 메세지를 입력해주세요');
} else {
//status 500
console.error(err);
}
});
};
server) DB에서 그 githubID을 가진 유저의 email을 찾아 응답으로 보내준다.
- Server 파트는 HJ님께서 구현해주신 것이다.
const { users } = require('../../models');
module.exports = {
post: (req, res) => {
const { githubId } = req.body;
users
.findOne({
where: {
githubId: githubId,
},
})
.then((data) => {
if (!data) {
res.status(400).send('have to apply github Id');
} else {
const useremail = data.email;
res.status(200).json(useremail);
}
})
.catch((err) => {
res.status(500).send('err');
});
},
};
※
항상 컴포넌트 틀을 잡거나 API를 사용하는 것 보다 리다이렉트에 대해 더 공부를 해겠다는 생각이 든다. 언제
this.props.history.push('/login'); 을 쓰는지, window.location = '/login'을 쓰는지, res.redirect('/') 을 쓰는지.. 에 대해서 명확하게 정리를 해봐야겠다.
(오늘(11/1) 대충 window.location = '/' 와 this.props.history.push('/')의 차이를 알것 같기도 하다..
아래는 Nov 1, 2020회고인데, 여기에 정리를 조금 해 보았다.)
2. Findpw 구현 - (Oct 26, 2020) 회고
사용자가 자신의 email과 githubID를 입력하고 제출하면 그걸 server의 findpw API로 post 요청을 한다.
서버는 해당하는 password를 찾아서 사용자의 이멜일로 보내준다.
clint는 응답을 받으면 alert 창을 통해 띄우고, 사용자가 확인 버튼을 누르면 login 페이지로 리다이렉트한다.
Client)
handleFindPwButton = () => {
axios({
method: 'post',
url: 'http://localhost:4000/users/login/findpw',
data: {
useremail: this.useremail,
githubId: this.githubId,
},
})
.then((res) => {
if (res.data !== null) {
alert('password를 회원님의 이메일로 전송하였습니다. 로그인 페이지로 이동 하시겠습니까?');
this.props.history.push('/Login');
} else {
alert(
'회원 정보가 존재하지 않습니다. email과 Github Id를 확인해주세요. 혹시 회원이 아니신가요?',
);
}
})
.catch((err) => {
if (err.message === 'Request failed with status code 400') {
alert('올바른 email과 Github Id를 입력해주세요.');
}
});
};
Server) HJ님께서 nodemailer 모듈을 사용하여 'password를 찾아서 사용자의 이멜일로 보내주는 기능' 구현해주셨다.
nodemodule은 보안성이 좋고 Gmail을 사용하면 하루에 최대 500통의 메일을 보낼 수 있다.
아래 코드는 HJ님 블로그글 <node-express 서버로 필요한 데이터 메일로 보내기>에서 더욱 자세한 설명과 함께 볼 수 있다.
const { users } = require('../../models');
//우리가 사용자의 데이터를 저장해두고 찾는 테이블
const nodemailer = require('nodemailer');
//nodemailer 모듈 설치
const user = process.env.findpw_mail;
const password_send = process.env.findpw_pw;
//이건 저희 개별 계정으로 연습?하거나 흠 각자의 서버에 저장된 개인 메일이나 비번을 활용하는게 좋을거 같아서 환경변수 설정함.
module.exports = {
post: (req, res, next) => {
const { useremail, githubId } = req.body;
users
.findOne({
where: {
email: useremail,
githubId: githubId,
},
})
.then((data) => {
if (!data) {
res.status(400).send('informations are not matched or have to sign up ');
} else {
const useremail = data.email;
const password = data.password;
//이건 보내는 사람의 정보를 입력하는 것(즉 서비스 제공자)
let transporter = nodemailer.createTransport({
service: 'gmail',
//지메일의 경우, 보내는 사용자의 계정이 보안수준이 낮은 접근 허용불가로 되어있으면 에러가 나는 경우가 있으므로 참고
auth: {
user: user,
pass: password_send,
},
});
//메일 보내는 실질적은 내용 구성
let mailOptions = {
from: user, //보내는 사람 메일주소
to: useremail, //받는 사람 메일주소
subject: 'S*FU Password 찾기',
html: `<p>${useremail} 계정의 임시 비밀번호는 <strong>${password}<strong>입니다.</p>`, // 메일내용
};
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
next(error);
} else {
console.log('Email sent: ' + info.response);
return res.status(200).json({ success: true });
}
});
}
})
.catch((err) => {
res.status(500).send('err');
});
},
};
예전에 office hour때 피드백을 받은 바에 의하면 이메일로 바로 비밀번호를 알려주는 것 보다. 비밀번호 변경 링크를 보내주는게 더 좋다고 하셨다. 그건 일단 Bare Minimum에 해당하는 기능을 다 구현 한 뒤 HE님께서 맡아서 구현해 주시기로 하였다.
모듈을 사용할 때마다 느끼는 것은 Nodemailer처럼 무척 유용한 모듈도 있지만 무조건 모듈을 사용한다고 해서 간편하거나 쉬운 것은 아니고 오히려 원리를 알고 직접 구현 할 때가 더 자유도가 높고 편한 경우도 많다는 것이다.
이를 판단해서 적절할 때 적합한 모듈을 쓰는 것도 어느정도의 내공이라고 생각한다.
reference
'Project > [SAFU] 1st Project' 카테고리의 다른 글
8. [Client & Server] Mypage와 Edit Userinfo (Oct 26, 2020 ~ Oct 30, 2020회고) (0) | 2020.11.06 |
---|---|
7. [Client] React Routing (Oct 24, 2020, Nov 1, 2020회고) (0) | 2020.11.05 |
5. [Client & Server] Login, Logout 구현 (Oct 21, 2020 ~ Oct 25, 2020 회고) (0) | 2020.11.05 |
4. [Client & Server] Signup 구현 (Oct 17, 2020 ~ Oct 20, 2020 회고) (0) | 2020.11.05 |
3. [Server] Sequelize DB 세팅(Oct 17~18, 2020 회고) (0) | 2020.11.05 |