오늘 수업 : ajax(axios)를 사용해서 로그인, 회원가입 server html에 reloading없이 alert 등을 바로 띄우는 기술 (?) 을 공부함.
1. 로그인 시 DB에 있는 Data와 비교해서 로그인 실패(alert) 구현하기
routers - user - user.controller.js
login_check 기존 코드
let login_check = async (req,res)=>{
let userid = req.body.userid;
let userpw = req.body.userpw;
let result = await User.findOne({
where:{userid, userpw}
})
req.session.uid = userid;
req.session.isLogin = true;
req.session.save(()=>{
res.redirect('/');
})
}
- > 비동기식으로 client가 login.html (input type="post") 에서 입력한 userid, userpw 과 같은 row 를 DB에서 찾아서 result 라는 변수에 넣음 -> DB에 있는 id, pw와 DB에 없는 id, pw로 console.log(result) 를 찍어 나오는 결과를 비교
DB에 존재하는 id, pw으로 로그인 - result 값 ↓↓↓
User {
dataValues: {
id: 3,
userid: '아이노유',
userpw: '1234',
username: '이힛',
gender: false,
userimage: null,
userdt: 2021-05-10T13:39:41.000Z
},
_previousDataValues: {
id: 3,
userid: '아이노유',
userpw: '1234',
username: '이힛',
gender: false,
userimage: null,
userdt: 2021-05-10T13:39:41.000Z
},
_changed: Set(0) {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
raw: true,
attributes: [
'id',
'userid',
'userpw',
'username',
'gender',
'userimage',
'userdt'
]
},
isNewRecord: false
}
DB에 존재하지않는 id, pw로 로그인한 경우 result값 ↓↓↓
NULL
1-1. result의 나오는 다른 결과값들을 이용해서 if 문으로 만들기
let login_check = async (req,res)=>{
let userid = req.body.userid;
let userpw = req.body.userpw;
let result = await User.findOne({
where:{userid, userpw}
})
if(result == null){ /// result의 값이 null 이면 = DB에 없다면 = id, pw가 틀리다면
res.redirect('/user/login'); //login 하는 page로 돌아가 !
}else{
req.session.uid = userid;
req.session.isLogin = true;
req.session.save(()=>{
res.redirect('/');
})
}
}
이제 로그인 실패로 다시 login.html로 돌아갔을 때 alert로 '입력 오류' 창을 뜨게 만들기
그 기준(?)을 만들기 위해 res.redirect('/user/login/flag=0') flag라는 속성에 0을 넣고 url 보내기
- > user.controller.js 의 login 부분에 받은 req.query.flag 값을 받고 넘기기
1-2. user.controller.js - login_check 부분
let login_check = async (req,res)=>{
let userid = req.body.userid;
let userpw = req.body.userpw;
let result = await User.findOne({
where:{userid, userpw}
})
if(result == null){ /// result의 값이 null 이면 = DB에 없다면 = id, pw가 틀리다면
res.redirect('/user/login?flag=0'); //login 하는 page로 돌아가 !
}else{
req.session.uid = userid;
req.session.isLogin = true;
req.session.save(()=>{
res.redirect('/');
})
}
}
1-3. user.controller.js - let login 부분
let login = (req,res)=>{
let flag = req.query.flag;
res.render('./user/login.html',{flag});
}
flag 값을 login.html 로 보냄
1-4. login.html
login.html <br/>
<form method = "post" action ="/user/login_check">
<table>
<tr>
<td>아이디</td>
<td>
<input type ="text" id ="userid" name = "userid">
</td>
</tr>
<tr>
<td>비밀번호 </td>
<td>
<input type ="text" id ="userpw" name = "userpw">
</td>
</tr>
</table>
<input type ="submit" value = "로그인하기">
</form>
{% if flag=="0" %}
<script type="text/javascript" >
alert('아이디, 패스워드 오류입니다.')
</script>
{% endif %}
{% if %} 절, flag 값을 활용해서 alert창 띄우기
1-5. alert 창 띄워진 이후의 id, pw text 창의 색 바꾸고 focus = 마우스 커서를 그 안으로 옮기면 , 클릭하면 색이 다시 하얘지도록 만들기
{% if flag=="0" %}
<script type="text/javascript" >
alert('아이디, 패스워드 오류입니다.')
let userid = document.querySelector('#userid');
let userpw = document.querySelector('#userpw');
userid.setAttribute('style', 'background:lightsalmon');
userpw.setAttribute('style', 'background:lightsalmon');
userid.addEventListener('focus', ()=>{
userid.setAttribute('style', 'background:#fff')
})
userpw.addEventListener('focus', ()=>{
userpw.setAttribute('style', 'background:#fff')
})
</script>
{% endif %}
2. 로그인 성공 시 회원정보 볼 수 있는 info page 구현
routers-user-user.controller.js
let info = async (req,res)=>{
let result = await User.findAll({});
res.render('./user/info.html',{result})
// console.log(result)
}
2-1. 원래 설정해놓았던 res.json({result}) -> render('./user/info.html')로 변경
2-2. 로그인한 userid 만 나오도록 설정
let info = async (req,res)=>{
let userid = req.query.userid;
let result = await User.findAll({
where:{userid,}
});
console.log(result);
res.render('./user/info.html',{
result:result[0]
})
// console.log(result)
}
2-3. views - user - info.html 도 변경 (result가 1개가 나와서 for 구문이 필요없음)
<table>
<tr>
<td>번호</td>
<td>아이디</td>
<td>비번</td>
<td>이름</td>
<td>성별</td>
<td>사진</td>
<td>등록일</td>
</tr>
<tr>
<td>{{result.dataValues.id}}</td>
<td>{{result.dataValues.userid}}</td>
<td>{{result.dataValues.userpw}}</td>
<td>{{result.dataValues.username}}</td>
<td>{{result.dataValues.gender}}</td>
<td>{{result.dataValues.userimage}}</td>
<td>{{result.dataValues.userdt}}</td>
</tr>
</table>
여기서 시간을 오래 잡아먹은 부분 ! --> User.findAll 인 경우 userid 1가지만 값을 찾아와서 result:result[0] 이렇게 값을 넘겨줘야 했고 User.findOne()을 쓴다면 result:result 이렇게 써야 가능했다.
findAll 전부를 찾아오는 개념 (비록 1개를가져와도) 변수에 넣을 때는 [0] 배열의 첫번째라고 사용
findOn 한개를 찾아오는 개념 -> 변수에 넣을 때 가져온 result 값을 그대로 넣어도 됨.
즉, 아래와 같이도 가능 !
routers - user - user.controller
let info = async (req,res)=>{
let userid = req.query.userid;
let result = await User.findOne({
where:{userid}
});
res.render('./user/info.html', {
result, // result:result
})
}
3. 날짜 Dateformat 바꾸기
models - user.js 에서 애초에 table을 만들 때 날짜를 변환해서 table을 만들기
3-1. userdt 부분 코드 추가
userdt:{
type:Sequelize.DATEONLY,
allowNull:false,
defaultValue:Sequelize.NOW,
get:function(){
return moment(this.getDataValue('userdt')).format('YYYY-MM-DD')
}
}
DATE --> DATEONLY
get:function(){~} 추가
this.getDataValue('userd') - class 활용
3-2. npm install moment 다운
3-3. server.js 덮어쓰기 true로 변경
sequelize.sync({force:true})
3-4. server on
table이 새로 덮여쓰였으니 data가 없다. 회원가입 추가 하기
추가할 때는 false로 변경해주기 (true 상태면 계속 전체 덮여쓰기가 되어 회원은 1명뿐임 )
sequelize.sync({force:false})
3-5. login -> 나의 정보 보기 (info.html) 가서 날짜 잘 나오는지 확인
4. 회원가입 시 image upload 가능하게 만들기
( HTMl form ----post(image)---> SERVER )
4-1. image를 받을 수 있는 공간 만들기
views = join.html
<tr>
<td>이미지</td>
<td>
<input type ="file" name ="img" >
</td>
</tr>
* 받을 확장자도 정할 수 있음 (지금은 사용x )
<input type ="file" name ="userimage" accept="image/png, image/jpg">
4-2. form 부분 enctype 추가 ( ≒ body 영역 확장)
<input type ="file" method="post"> 있으면 enctype 추가 하자
<form method = "post" action = "/user/join_success" enctype="multipart/form-data">
enctype = encoding type
multipart/form-data = 모든 문자를 인코딩하지 않겠다. (form으로 server에 이미지, 파일을 전송할 때 주로 사용)
http통신에 header/ body 있는데 post - body에 담아서 보내는..
이미지가 보내질 수 있게 form을 준비? 하는 개념
enctype 속성 알기
4-3. npm install multer 다운
내용을 가공해서 우리가 원하는 위치에 파일을 생성, 옮겨 확장자를 붙여 줌
multer ----> app.use('/', ____ another middle ware___, router) 이렇ㄱ ㅔ 미들웨어를 계속 추가할 수 있음
대신 next(); 가 붙어서 다음 것도 모두 실행되게 만들기
즉, 하나의 url 값에 두 가지의 callback함수가 들어갈 수 있다.
ex) 콜백함수 많구나 ~ next(); 가 있겠구나 ~ 생각하기
4-4. routers - user - index.js 에 multer 가져오기 / 환경설정 추가
action = "/user/join_success" -> post('/join_success) 하는 routers - user - index.js 에 코드 추가
routers - user - index.js
const express = require('express');
const router = express.Router();
const userController = require('./user.controller')
const multer=require('multer'); //추가1
const upload = multer({ // 추가2
storage:multer.diskStorage({ //storage: 어디에 저장
destination:function(req,file,callback){
callback(null,'uploads/')
},
filename:function(req,file,callback){ //filename: 어떤 이름으로 저장
callback(null,new Date().valueOf())
}
})
})
router.get('/join',userController.join);
router.post('/join_success', upload.single('img'),userController.join_success); //추가3
router.get('/login', userController.login);
router.post('/login_check', userController.login_check);
router.get('/logout', userController.logout);
router.get('/info', userController.info);
module.exports=router;
img 에 담은 엄~ 청 긴 text(image 도 text로 이루어져있) 를 따로 빼서 처리한 것 ( 너무큼)
4-5. npm install path 다운
4-6. routers - user - index.js 에 path 가져오기
const path = require('path'); //추가1
const upload = multer({
storage:multer.diskStorage({
destination:function(req,file,callback){
callback(null,'uploads/')
},
filename:function(req,file,callback){
callback(null,new Date().valueOf() + path.extname(file.originalname)) //추가2
}
})
})
추가 2 = 확장자 가져오는 코드
*path.extname(filePath);
파일 확장자 추출 후 출력
- 경로의 마지막 부분의 문자열에서 마지막 '.' 에서부터 경로의 확장자를 반환
- 경로의 마지막 부분에 '.'가 없어가 첫 글자가 '.'이라면 빈 문자열을 반환
4-7. uploads 폴더 (이미지 사진 저장되는 폴더) 만들기
4-8. server on -> 회원가입 -> upload 폴더 확인 -> 사진이 들어와 있어야함 !
5. image DB에 저장하기 (SERVER ---img--> DB)
DB에 img (엄청 큰 용량의 text)를 저장하지 않고 경로만 저장한다.
DB에 파일 경로만 넣어주면 끝 !
5-1. 파일 경로 가져오기
routers - user - user.controller.js
img 변수에 req.body.img 받은 거 넣고 insert, render에도 추가
let join_success = async(req,res)=>{
let userid = req.body.userid;
let userpw = req.body.userpw;
let username = req.body.username;
let gender = req.body.gender;
let userimage = req.file.path; //추가
await User.create({
userid,userpw,username, gender, userimage //추가
})
res.render('./user/join_success.html',{
userid, userpw, username, gender, userimage //추가
});
}
req.file.path -> 다른 변수들과 다른 이유
router.post('/join_success', upload.single('img'), userController.join_success);
여기서 처리했기 때문에 바로 사용가능하다.
5-2. server on -> 회원가입 -> mysql prompt check !
6. image html 화면에 뿌려보기 (DB---img--->SERVER---> HTML)
6-1. server.js 아래 추가
app.use(express.static('uploads'))
6-2. views-user - join_success.html
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
join_success.html <br/>
<div><img src = "http://localhost:3000/{{userimage}}"></div>
{{username}}님 환영합니다. <br/>
{{username}}님의 ID 는 {{userid}}입니다.
</body>
</html>
6-3. routers-user-use.controller.js
let join_success = async(req,res)=>{
let userid = req.body.userid;
let userpw = req.body.userpw;
let username = req.body.username;
let gender = req.body.gender;
let userimage = req.file.filename; // req.file.path---> req.file.filename수정
await User.create({
userid,userpw,username, gender, userimage
})
res.render('./user/join_success.html',{
userid, userpw, username, gender, userimage
});
}
req.file console.log 해보면 요렇게 나옴.
path, filename 을 내가 사용한 것
{
fieldname: 'img',
originalname: 'KakaoTalk_20201220_141237197.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'uploads/',
filename: '1620757206785.jpg',
path: 'uploads\\1620757206785.jpg',
size: 1619505
}
http://localhost:3000/~~~.jpg <-uploads/ 가 없는이유 : uploads도
app.use(express.static('uploads'))
server.js 에서 사용할거라고 해놔서 uploads 경로는 이미 있는 거라고 생각하기 !
7. image 안올린 경우, 예외처리 해주기 by 삼항 조건 연산자
회원가입 시, image 안올린 경우 console.log(req.file) 값 = undefined 가 나온다.
이걸 이용해서 삼항 조건 연산자 만들기
7-1. routers - user - user.controller.js 변수 userimage 수정
let userimage = req.file ==undefined ? '' : req.file.filename;
만약 req.file의 값이 undefined면 (이미지가 없으면) userimage의 값을 '' 아무것도 넣지 말고 이미지가 있으면 (undefined가 아니라면) req.file.filename을 넣어라