이번엔 브라우저에서 nodejs 서버로 데이터 삭제 요청 해볼게요
db로도 데이터 삭제 요청 할거임
이 포스팅은 시리즈니깐 내용 이해 안되면
nodejs 게시판에서 이전 글 한번 보고 오세요
1. server.js
// express로 서버 만들기 기본 셋팅
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
// bodyparser 사용 설정
app.use(bodyParser.urlencoded({extended: true}));
// ejs 사용 설정
app.set('view engine', 'ejs');
// 몽고DB랑 연결해주는 코드
const MongoClient = require('mongodb').MongoClient;
var db;
MongoClient.connect('mongodb+srv://bebsae:비밀번호@cluster0.kotmhwt.mongodb.net/?retryWrites=true&w=majority',
function(에러, client){
if(에러) {
return console.log(에러)
}
// 나는 몽고db atlas에 todoapp이라는 이름의 데이터베이스를 만들어둠
// 이 코드로 todoapp이라는 데이터베이스에 접속 가능
db = client.db('todoapp');
app.listen(8080, function(){
console.log('db connected')
})
})
/*
// listen(서버 띄울 포트번호, 띄운 후 실행할 코드)
app.listen(8080, function () {
console.log("서버 실행 중");
});
*/
// get('경로', 함수)
// function(요청, 응답)
app.get("/first", function (req, res) {
res.send("첫번째 페이지임");
});
app.get("/second", function (req, res) {
res.send("두번째 페이지임요");
});
// html파일 띄우는 소스
app.get("/", function (req, res) {
res.sendFile(__dirname + "/main.html");
});
app.get("/write", function (req, res) {
res.sendFile(__dirname + "/write.html");
});
// POST요청을 처리하는 소스
app.post("/add", function (req, res) {
res.send('전송완료');
console.log(req.body.title);
console.log(req.body.date);
var title = req.body.title;
var date = req.body.date;
// counter라는 collection에서 데이터 가져오는 코드
// 게시물갯수 라는 이름의 데이터를 찾아서 가져옴
db.collection('counter').findOne({name: '게시물갯수'}, function(에러, 결과){
console.log(결과.totalPost)
var 총게시물갯수 = 결과.totalPost;
// 몽고db atlas에 post라는 collection도 만들었었음
// db에 데이터 저장하는 코드임
// 데이터 양식은 {키 : 밸류} 형태임
// _id는 데이터의 인덱스값 같은거 적어주는거임
db.collection('post').insertOne({_id : 총게시물갯수+1, 제목 : title, 날짜 : date}, function(에러, 결과){
console.log('저장완료');
// db의 값을 업데이트(수정)하는 코드
// updateOne({수정할데이터},{$set : {수정값}},function(){})
// $set이 update operator(연산자)임, 값을 바꿔줌
// 연산자에는 $inc도 있음 이건 값을 더해줌
db.collection('counter').updateOne({name:'게시물갯수'},{$inc : {totalPost:1}},function(에러, 결과){
if(에러){
return console.log(에러)
}
});
});
});
});
// ejs파일 불러오는 코드
app.get('/list', function(req, res) {
// post라는 collection에서 모든 데이터 꺼내오기
db.collection('post').find().toArray(function(에러, 결과){
console.log(에러);
console.log(결과);
// DB에서 가져온 데이터를 ejs파일에 넣어 줌
// 데이터는 posts라는 변수에 넣어 줌
res.render('list.ejs', {posts : 결과});
});
});
app.delete('/delete', function(req, res){
console.log(req.body);
req.body._id = parseInt(req.body._id);
db.collection('post').deleteOne(req.body, function(에러, 결과){
console.log('삭제 완료');
// 성공 시 200번(성공) 응답 보냄
// 실패 시 400번(실패) 응답 보냄
// send 옵션으로 메시지도 보낼 수 있음
res.status(200).send({message: '성공했습니다'});
//res.status(400).send({message: '실패했습니다'});
});
});
우선 server.js파일의 전체코드임
그 중에서도
app.delete('/delete', function(req, res){
console.log(req.body);
req.body._id = parseInt(req.body._id);
db.collection('post').deleteOne(req.body, function(에러, 결과){
console.log('삭제 완료');
// 성공 시 200번(성공) 응답 보냄
// 실패 시 400번(실패) 응답 보냄
// send 옵션으로 메시지도 보낼 수 있음
res.status(200).send({message: '성공했습니다'});
//res.status(400).send({message: '실패했습니다'});
});
});
DB에 삭제 요청하는 코드는 이거임
만약에 /delete URL로 요청이 들어오면 뭔가 삭제를 시킬거임
뭘 삭제할거냐면...
그 내용은 req.body를 통해 브라우저에서 전달받은 데이터에 들어있음
parseInt(req.body._id)를 이용해서 웹으로부터 전달받은 데이터 중 _id값을 숫자(int)로 바꿔줌
숫자로 바꾼 값은 req.body._id에 저장함
이렇게 하면 브라우저에서 전달받은 _id값을 문자가 아니라 숫자로 전달할 수 있고
그래야 DB가 알아들음
그리고 deleteOne을 이용해서, req.body._id로 전달받은 id값을 가진 데이터를 삭제해줌
atlas 웹페이지에서 본 적 있는 이 _id값을 의미함
까먹은 사람을 위해 부연설명하자면
mongodb에 데이터 저장할때 각 데이터마다 저렇게 _id값이 주어짐
이게 고유 값이라서 각 데이터를 구분할 수 있게 도와줌
나는 7번 id를 가진 데이터를 삭제해야 하는데
막 암거나 삭제하면 안되니까 저렇게 고유값을 줘서
특정 데이터만 골라낼 수 있도록 하는 거임
삭제 성공하면 res.status(200).send({메시지내용})을 이용해서
브라우저로 성공 메시지를 보내줌
여기서 200이 뭐냐면 성공했다는 응답을 보내겠다는거임
저기서 status안에 들어있는 값을 400으로 바꾸면 실패했다는 응답을 보내는거임
2. list.ejs
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1 class="ml-2 my-3">할 일 리스트</h1>
<ul class="list-group">
<% for (var i = 0; i < posts.length ; i++){ %>
<li class="list-group-item">
<h4>글 번호 : <%= posts[i]._id %></h4>
<h4>할 일 제목 : <%= posts[i].제목 %></h4>
<h4>할 일 마감 날짜 : <%= posts[i].날짜 %></h4>
<button class="delete" data-id="<%= posts[i]._id %>">삭제</button>
</li>
<% } %>
</ul>
<script
src="https://code.jquery.com/jquery-3.6.3.js"
integrity="sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM="
crossorigin="anonymous"></script>
<script>
$('.delete').click(function(e){
// 내가 누른 요소의 data-id값을 '글번호'라는 변수에 저장
// e.target은 지금 클릭한 것을 의미
var 글번호 = e.target.dataset.id;
// this는 지금 이벤트가 동작하는 곳을 의미
var 지금누른거 = $(this);
$.ajax({
method : 'DELETE',
url : '/delete',
data : {_id : 글번호},
}).done(function(결과){
// 브라우저 콘솔에 뜸
console.log('성공했음');
// 지금 누른 버튼의 부모 태그를 찾아 줌
// fadeOut으로 해당 태그 사라지게 함
지금누른거.parent('li').fadeOut();
}).fail(function(xhr, textStatus, errorThrown){
console.log(xhr, textStatus, errorThrown);
});
});
</script>
<!-- Optional JavaScript; choose one of the two! -->
<!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
<!-- Option 2: Separate Popper and Bootstrap JS -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>
-->
</body>
</html>
이번엔 list.ejs파일의 전체 코드임
jquery 연결 코드가 기존이랑 바뀌었으니 참고하시길
왜 바꿨냐면 AJAX라는 문법을 jquery로 쓸건데 그거 적용하기 위해서임
<h1 class="ml-2 my-3">할 일 리스트</h1>
<ul class="list-group">
<% for (var i = 0; i < posts.length ; i++){ %>
<li class="list-group-item">
<h4>글 번호 : <%= posts[i]._id %></h4>
<h4>할 일 제목 : <%= posts[i].제목 %></h4>
<h4>할 일 마감 날짜 : <%= posts[i].날짜 %></h4>
<button class="delete" data-id="<%= posts[i]._id %>">삭제</button>
</li>
<% } %>
</ul>
우선 바디태그에서
데이터를 좀 이쁘게 꾸몄음
웹에 표시되는 데이터를 표에 집어넣어 준 것
거기다가 삭제 버튼도 하나 만들고
data-id라는 속성도 넣어줬다
저게 뭐냐면 posts[i]._id 값을 html요소에 집어넣을때 쓰는 속성임
왜 이걸 하냐면 내가 누른 삭제버튼이
몇번 id를 가진 데이터의 삭제 버튼인지 알아야하기 때문
삭제버튼 눌렀는데 암거나 막 삭제되면 안되잖아요
$('.delete').click(function(e){
// 내가 누른 요소의 data-id값을 '글번호'라는 변수에 저장
// e.target은 지금 클릭한 것을 의미
var 글번호 = e.target.dataset.id;
// this는 지금 이벤트가 동작하는 곳을 의미
var 지금누른거 = $(this);
$.ajax({
method : 'DELETE',
url : '/delete',
data : {_id : 글번호},
}).done(function(결과){
// 브라우저 콘솔에 뜸
console.log('성공했음');
// 지금 누른 버튼의 부모 태그를 찾아 줌
// fadeOut으로 해당 태그 사라지게 함
지금누른거.parent('li').fadeOut();
}).fail(function(xhr, textStatus, errorThrown){
console.log(xhr, textStatus, errorThrown);
});
});
다음은 script태그 부분임
저기 위에서 delete클래스를 갖고있는 버튼을 눌렀을때,
'글번호'라는 변수에 해당 버튼의 data-id에 들어있는 값을 저장해줌
e.target이 지금 클릭한 요소를 의미함
그리고 '지금누른거'라는 변수에 해당 이벤트가 동작중인 요소를 지정해줌
$.ajax({
method : 'DELETE',
url : '/delete',
data : {_id : 글번호},
}).done(function(결과){
// 브라우저 콘솔에 뜸
console.log('성공했음');
// 지금 누른 버튼의 부모 태그를 찾아 줌
// fadeOut으로 해당 태그 사라지게 함
지금누른거.parent('li').fadeOut();
}).fail(function(xhr, textStatus, errorThrown){
console.log(xhr, textStatus, errorThrown);
});
이게 AJAX 문법인데 AJAX는 서버랑 통신할때 쓰는 자바스크립트 문법임
새로고침 없어도 서버랑 통신할 수 있는 아주 유용한 문법이라는데
암튼 AJAX문법이 편하니깐 이걸로 서버랑 통신해봅시다
method는 DELETE로 주세요
우린 데이터 삭제할거니깐
그리고 url은 /delete로 요청할겁니다
app.delete('/delete', function(req, res){
console.log(req.body);
req.body._id = parseInt(req.body._id);
db.collection('post').deleteOne(req.body, function(에러, 결과){
console.log('삭제 완료');
// 성공 시 200번(성공) 응답 보냄
// 실패 시 400번(실패) 응답 보냄
// send 옵션으로 메시지도 보낼 수 있음
res.status(200).send({message: '성공했습니다'});
//res.status(400).send({message: '실패했습니다'});
});
});
아까 server.js에서 /delete라는 URL을 요청받으면 DB에 있는 데이터 삭제하도록 코드 짠거 기억하시져?
마지막으로 data는 _id요소에 들어있는 '글번호' 변수의 값으로 전달합니다
자 이렇게 AJAX문법으로 DELETE요청을 서버에 보냈음
만약 요청이 성공하면?
}).done(function(결과){
// 브라우저 콘솔에 뜸
console.log('성공했음');
// 지금 누른 버튼의 부모 태그를 찾아 줌
// fadeOut으로 해당 태그 사라지게 함
지금누른거.parent('li').fadeOut();
done에 들어있는 이 코드를 실행해줌
'지금누른거' 변수에 들어있는 요소(지금 누른 버튼)의 부모 태그 중 li태그를 fadeOut(서서히 사라지게 하는 역할) 시켜줌
}).fail(function(xhr, textStatus, errorThrown){
console.log(xhr, textStatus, errorThrown);
});
그리고 실패하면 fail에 들어있는 코드 실행시켜줌
저기 변수가 3개나 들어가는데 에러 찍어주는 변수임
머선 에러인지 알려주는 변수니까 혹시 에러나서 로그 뜨면 잘 살펴보고 해결하면 됨ㅎ
정리하자면,
list.ejs에서는
(1) 내가 누른 버튼의 data-id에 저장되어있는 데이터를 '글번호'라는 변수에 저장했음
(2) ajax문법을 이용해 DELETE요청을 하는데, '글번호'변수에 들어있는 값을 /delete라는 URL로 전달함
(3) 만약에 성공했다면 '성공했음'이라고 콘솔(브라우저의)에 띄워줌
(4) '지금누른거'라는 변수에 $(this)가 저장되어 있는데 지금 누른 요소를 의미함. 그 요소의 부모태그 중 <li>태그의 내용을 fadeOut 시켜줌
server.js에서는
(1) /delete라는 URL로 삭제 요청이 들어오면 요청값을 req.body._id에 숫자 형태로 저장 함
(2) DB의 post라는 collection에 있는 데이터 중 req.body값을 가진 데이터 한 개를 삭제해줌
(3) 삭제 성공하면 콘솔(터미널)에 '삭제 완료'라고 띄워줌
(4) 브라우저로 status값이랑 메시지를 전달함