서버에는 data가 넘어오지만 DB에는 반영되지 않게
edit으로 post요청
보통 화면 보기는 get방식
post로 하는 이유
: content에서 edit으로 넘길 데이터가 많아서
- 제목을 클릭하면 나오는 상세페이지를 모달로 띄움
- 모달을 이용하여 바로 수정이 가능하도록 변경
- 수정된 내용은 바로 목록에 반영하여 보여지도록 함
- _id에 따라 상세페이지 띄우는 /content와 수정을 위한 /edit, edit.ejs가 필요없어짐
(modal에 를 추가하여 id를 받아 사용)
updateOne(조건, 변경항목)
app.post('/update', (req, res) =>{
console.log(req.body);
mydb.collection('post')
.updateOne({_id:new ObjId(req.body._id)},
{$set: {title:req.body.title, content:req.body.content, date:req.body.someDate} })
.then(result => {
//res.redirect('/list');
list(req,res);
})
.catch(err => {
console.log(err);
res.status(500).send();
});
});
list.ejs
<!-- The Modal -->
<form action="/update" method="post">
<span id="hiddenSpan"></span>
<!-- db update를 위한 _id 값을 담기 위함(숨김처리) -->
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
제목 : <div><h4 class="modal-title" id="postTitle"></h4></div>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<!-- Modal body -->
<div class="modal-body" >
<div>
내용 : <span id="postContent"></span>
</div>
<p></p>
<div>
작성일 : <span id="postDate"></span>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<span id="updateSpan">
<button type="button" class="btn btn-info" onclick="editDisplay()">수정하러가기</button>
</span>
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</form>
...
<tr>
<!-- 타이틀 부분을 클릭하면 모달 띄워지게
이때 모달창에 data가 전달됨 -->
<td data-bs-toggle="modal" data-bs-target="#myModal">
<a href="#" onclick="modal_content(`<%= data[i]._id %>`,`<%= data[i].title %>`,`<%= data[i].content %>`, `<%= data[i].date %>`)"><%= data[i].title %></a></td>
<td><%= data[i].date %></td>
<td><button class = 'delete btn btn-outline-danger' data-id = '<%= data[i]._id %>'>삭제</button></td>
</tr>
...
<script>
let modalData;
// 모달창에 보이게할 내용 설정 함수
function modal_content(_id, title, content, date){
modalData={_id, title, content, date};
$('#postTitle').text(`${modalData.title}`);
$('#postContent').text(`${modalData.content}`);
$('#postDate').text(`${modalData.date}`);
$('#updateSpan').html(`<button type="button" class="btn btn-info" onclick='editDisplay()'>수정하러가기</button>`);
// 마지막 줄이 추가되어 있지 않으면 '수정하러가기'가 아닌 '수정' 버튼이 뜰 수 있음 (동적이라서 생기는 문제)
}
// 수정하기 버튼 클릭 시 수정 가능하게 바꿔주는 함수
function editDisplay() {
//console.log(modalData._id, modalData.title, modalData.content, modalData.date);
$('#hiddenSpan').html(`<input type='hidden' value='${modalData._id}' name='_id'>`);
$('#postTitle').html(`<input value='${modalData.title}' name='title'>`);
$('#postContent').html(`<textarea name='content'>${modalData.content}</textarea>`);
$('#postDate').html(`<input type='date' value='${modalData.date}' name='someDate'>`);
$('#updateSpan').html(`<button type="submit" class="btn btn-warning" >수정</button>`);
}
// 모달 안에서 사용되어 submit 타입의 버튼 클릭 시 모달 맨 처음 부분에 설정되어 있는 action="/update"로 인해 /update로 데이터가 넘어감
</script>
목표: 어디에서 렌더링할것이냐
CCR/SCR가 아니라 성능이 목표
-> DB까지 가서 가져오는것 보다 Server에 있는 것을 가져오는 것이 성능이 좋음
-> update를 DB에 적용하고 그 결과를 redirect로 가져오면 db에서 다시 데이터를 가져옴
결과를 foward
server에서 update 후 list에 적용하는게 forward
보안 상에도 redirect는 안좋음
중간에 해커가 요청을 변조할 수 있음
https://velog.io/@bongf/learned-redirect-forward
https://nesoy.github.io/articles/2018-04/Redirect-Forward
URL의 변화여부가 필요하다면 Redirect를 사용하는 것이 좋습니다.
객체를 재사용하거나 공유해야한다면 Forward를 사용하는 것이 좋습니다.
app.get('/cookie', (req,res)=>{
res.cookie('milk', `1000원`);
res.send('쿠키 설정 완료');
});
app.get('/cookie', (req,res)=>{
let milk = parseInt(req.cookies.milk) + 1000;
// 맨 처음에는 milk라는 쿠키가 존재하지 않아서 NaN이 나옴
if(isNaN(milk)){
milk = 0;
}
res.cookie('milk', milk);
res.cookie('name', '이지우');
//res.send('쿠키 설정 완료');
res.send('product : ' + req.cookies.milk + " / name : " + req.cookies.name);
// send는 두번 실행 안됨
// send를 작성하지 않아도 브라우저 헤더를 통해 쿠키가 넘어감
});
res.cookie('milk', milk, {maxAge : 1000});
1초 전에 새로고침하면 1000씩 증가되지만
1초 후에 새로고침하면 다시 1000이 됨 (화면에는 0)
값부분에 쓰여있는 것은 암호화가 아니라 인코딩된 것
const cookieParser = require('cookie-parser');
app.use(cookieParser('암호화키')); // 암호화키 부분에는 아무거나 들어가도 됨
app.get('/cookie', (req,res)=>{
let milk = parseInt(req.signedCookies.milk) + 1000; // 암호화된 쿠키값
if(isNaN(milk)){
milk = 0;
}
res.cookie('milk', milk, {signed:true}); // 암호화하여 보이게
res.cookie('name', '이지우');
//res.send('쿠키 설정 완료');
res.send('product : ' + req.signedCookies.milk + " / name : " + req.cookies.name);
// send는 두번 실행 안됨
});
저장할 때는 주로 텍스트 형태로 저장
객체 형태 그대로 저장도 가능
let session = require("express-session");
app.use(
session({
secret : 'asdfasdfasf',
resave : false, // 접속할 때마다 새로운 세션id 발급 여부
saveUninitialized: true, // 세션 사용하기 전까지 세션id 발급 안함
})
);
app.get("/session", function (req, res) {
console.log(req.session.milk);
if(isNaN(req.session.milk)){
req.session.milk = 0;
}
req.session.milk = req.session.milk + 1000;
res.send("session : " + req.session.milk + "원");
});
connect.sid라는 이름의 키값이 저장됨
login.ejs (enter.ejs 수정하여 사용)
<div class = "container mt-4">
<form action = "/login" method="post"> <!-- post 방식으로 넘김 -->
<div class = "form-group">
<label>아이디</label>
<input type="text" name = "userid" class = "form-control">
</div><p></p>
<div class="form-group">
<label>비밀번호</label>
<input type="text" name ="userpw" class="form-control">
</div><p></p>
<button type = "submit" class="btn btn-warning" style="float:right">로그인</button>
</form>
</div>
server.js (get, post 라우터 모두 설정)
app.get("/login", (req, res) =>{
console.log('로그인 페이지');
res.render('login.ejs');
});
app.post('/login', (req, res) =>{
console.log('아이디 : '+ req.body.userid);
console.log('비밀번호 : '+ req.body.userpw);
res.send('로그인 되었습니다.');
});
server.js
app.post('/login', (req, res) =>{
console.log('아이디 : '+ req.body.userid);
console.log('비밀번호 : '+ req.body.userpw);
mydb
.collection('account')
.findOne({userid : req.body.userid})
.then(result => {
if(result.userpw == req.body.userpw){
res.send('로그인 되었습니다.');
}else{
res.send('비밀번호가 틀렸습니다.');
}
});
});
findOne으로 db에 저장된 userid와 입력된 userid가 같은 값의 데이터 가져오기(result)
이 데이터의 userpw가 입력된 userpw와 같으면 로그인 되도록 로직 추가
❗ 여기에서 입력된 userid 값이 db에 없으면 userpw를 가져올 수 없어 에러 발생함
app.get("/login", (req, res) =>{
console.log(req.session);
if(req.session.user){
// 로그인 시 req.session.user 세션 데이터가 존재하면 로그인 상태인 것으로 간주함
console.log('세션 유지');
res.send('로그인 되었습니다.');
}else{
res.render('login.ejs');
}
});
app.post('/login', (req, res) =>{
console.log('아이디 : '+ req.body.userid);
console.log('비밀번호 : '+ req.body.userpw);
mydb
.collection('account')
.findOne({userid : req.body.userid})
.then(result => {
if(result.userpw == req.body.userpw){
req.session.user = req.body;
console.log('새로운 로그인');
res.send('로그인 되었습니다.');
}else{
res.send('비밀번호가 틀렸습니다.');
}
});
});
db의 데이터와 입력한 id, pw가 일치하면 req.body에 있는 데이터(입력한 id, pw)가 req.session.user 세션에 추가됨
로그인 성공한 뒤 브라우저를 닫고 다시 /login에 접속하면 바로 로그인 성공 페이지가 띄워짐
app.get('/logout', (req, res) => {
console.log('로그아웃');
req.session.destroy(); // 세션 삭제
res.redirect('/');
});
로그인 후 세션이 있는 상태에서 /logout에 접속하면 홈화면으로 이동하면서 세션이 삭제됨
app.post('/login', (req, res) =>{
console.log('아이디 : '+ req.body.userid);
console.log('비밀번호 : '+ req.body.userpw);
mydb
.collection('account')
.findOne({userid : req.body.userid})
.then(result => {
if(result.userpw == req.body.userpw){
req.session.user = req.body;
console.log('새로운 로그인');
res.render('index.ejs', {user:req.session.user});
}else{
res.render('login.ejs');
}
});
});
app.get('/logout', (req, res) => {
console.log('로그아웃');
req.session.destroy(); // 세션 삭제
res.render('index.ejs', {user:null});
});
index.ejs
<h1>홈입니다.</h1>
<% if(user){ %>
<h3>반갑습니다. <%= user.userid %>님.</h3>
<a href="/logout">로그아웃</a>
<% }else{%>
<h3>로그인 해주세요.</h3>
<p><p>
<button class="w-100 btn btn-warning login"><b>로그인</b></button>
<% }%>
<script>
$('.login').click(function(e){
location.href='/login';
})
</script>
localhost:8080/
에 접속하면 ReferenceError: D:\study\JavaScript\01_WEB\06_24_login\views\index.ejs:14
12| <h1>홈입니다.</h1>
13|
>> 14| <% if(user){ %>
15| <h3>반갑습니다. <%= user.userid %>님.</h3>
16| <a href="/logout">로그아웃</a>
17| <% }else{%>
user is not defined