[Node.js] chap.2
mongoDB
NoSQL 데이터베이스
- 처음 다룰 때 어려운 셋팅작업이 필요하지 않음 (스키마 생성 등 필요없음)
- SQL 안배워도 됨
- 복잡한 자료형 몰라도 됨
- 평생 무료 호스팅해주는 곳이 있음
mongodb+srv://디비계정아이디:디비계정패스워드@cluster0-qaxa3.mongodb.net/데이터베이스이름?retryWrites=true&w=majority
계정 생성 후 Database Access, Network Access 완료 후에 Databases Connect 하는 부분에서 커넥션 하기 위한 접속URL 코드를 가져올 수 있다.
npm install mongodb
mongodb 라이브러리 설치
- mongoDB 연결
const MongoClient = require('mongodb').MongoClient;
MongoClient.connect('아까 챙겨온 접속URL', function(에러, client){
if (에러) return console.log(에러);
//서버띄우는 코드 여기로 옮기기
app.listen('8080', function(){
console.log('listening on 8080')
});
})
접속 URL: mongodb+srv://디비계정아이디:디비계정패스워드@cluster0-qaxa3.mongodb.net/데이터베이스이름?retryWrites=true&w=majority
* DB에 자료 저장하기
mongoDB의 Databases 부분의 collections 에서 database를 생성한다. (database name과 collection name을 생성) database는 하나의 폴더, collection은 하나의 엑셀파일이라고 생각하자.
var db; // 페이지 전체에서 쓸 수 있는 전역 변수
MongoClient.connect('접속URL', { useUnifiedTopology: true }, function (에러, client) {
if (에러) return console.log(에러)
db = client.db('todoapp'); // database에 접속
db.collection('post').insertOne( {이름 : 'John', _id : 100} , function(에러, 결과){ // 자료추가
console.log('저장완료');
});
app.listen(8080, function () {
console.log('listening on 8080')
});
});
({ useUnifiedTopology: true }는 warning message를 제거해준다.)
db.collection('post')는 collection 중 'post'를 선택 한다는것이고 insertOne은 하나의 자료를 저장한다. 자료형식은 object형으로 저장할 수 있다. _id는 하나의 자료의 유일한 키값을 지정하기 위해 사용한다.
ex)
app.post('/add', function(req, res){
db.collection('post').insertOne({제목: req.body.title, 날짜: req.body.date}, function(error, result){
console.log('성공');
})
res.send('전송 완료')
})
/add 라는 URL로 요청을 보내면 해당 데이터를 저장할 수 있다. res.send() 이 부분은 필히 존재해야 한다. 전송이 성공하든 실패하든 서버에서 뭔가를 보내주어야 한다. 메세지 뿐만 아니라 간단한 응답코드나 리다이렉트 등을 사용할 수도 있다.
* HTML에 데이터 가져오기
HTML만 보내면 정적(static)페이지가 된다. HTML에 실제 DB 데이터를 넣어서 보내려면, EJS, PUG같은 템플릿 엔진을 사용해야 한다.
npm install ejs // ejs 라이브러리 설치
...
app.set('view engine', 'ejs'); // Server.js 상단
...
- EJS 파일 생성
(views/list.ejs)
<!doctype html>
<head>
index.html에 있던거 전부 복붙
</head>
<body>
index.html에 있던거 전부 복붙
</body>
</html>
파일명을 list.ejs라고 생성했다면 작업 폴더 내에 views라는 폴더 안에 만들어 그 안에 저장해야 한다.
- DB에서 데이터 가져오기
// (server.js)
app.get('/list', function(요청, 응답){
db.collection('post').find().toArray(function(에러, 결과){
console.log(결과)
응답.render('list.ejs', { posts : 결과 })
})
})
post라는 collection에서 find로 데이터를 가져오는데 array형식으로 가져온다. 후에 ejs파일을 렌더링하는 작업을 거쳐서 'posts'라는 이름으로 object의 자료를 전달한다.
// (views/list.ejs)
<% for (var i = 0; i < posts.length; i ++) { %>
<h4><%= posts[i].제목 %></h4>
<p><%= posts[i].날짜 %></p>
<% } %>
전달한 'posts' 자료는 array형태로 전달된 object이기 때문에 <% %> 안에 object나 array 형의 자료를 조회할 때처럼 사용한다.
_id (like pk)
MongoDB는 데이터를 저장할 때 _id 값을 저장하지 않으면 ObjectId() 값을 강제로 부여한다. 이 값을 알아보기 쉽고 관리하기 쉽게 만들기 위해서는 _id를 강제로 달아주면 된다.
- auto Increment처럼 사용하기
app.post('/add', function(요청, 응답){
응답.send('전송완료');
db.collection('post').insertOne( { _id : 지금까지 발행한 게시물 갯수 + 1, 제목 : 요청.body.title, 날짜 : 요청.body.date } , function(){
console.log('저장완료')
});
});
post collection에 _id 값을 부여한다.
새로운 counter라는 collection을 생성한다. 해당 collection은 지금까지 몇번 게시물을 발행했는지 기록하는 부분이다.
app.post('/add', function(요청, 응답){
db.collection('counter').findOne({name : '게시물갯수'}, function(에러, 결과){
var 총게시물갯수 = 결과.totalPost;
db.collection('post').insertOne( { _id : (총게시물갯수 + 1), 제목 : 요청.body.title, 날짜 : 요청.body.date } , function(){
console.log('저장완료')
응답.send('전송완료');
});
});
});
post collection에 데이터를 저장할 때, _id 값으로 counter collection에 있는 총 게시물 갯수(totalPost)를 가져와서 +1 한 값으로 저장해준다.
* DB Update & 연산자
- 연산자
{ $set: {totalPost: 100} } => totalPost 값 100으로 변경하기
{ $inc : { totalPost : 5 } } => totalPost 값 5 증가하기
db.collection('counter').updateOne( {name : '게시물갯수' } , { $inc : { totalPost : 1 } } , function(에러, 결과){
console.log('수정완료')
})
update의 경우엔 콜백함수를 제외한 파라미터가 2개 들어가는데, 특이하게 2번째 파라미터엔 연산자(operator)가 들어가야 한다.
ex)
app.post('/add', function (요청, 응답) {
db.collection('counter').findOne({name : '게시물갯수'}, function(에러, 결과){
var 총게시물갯수 = 결과.totalPost
db.collection('post').insertOne({ _id : 총게시물갯수 + 1, 제목 : 요청.body.title, 날짜 : 요청.body.date }, function (에러, 결과) {
db.collection('counter').updateOne({name:'게시물갯수'},{ $inc: {totalPost:1} },function(에러, 결과){
if(에러){return console.log(에러)}
응답.send('전송완료');
})
})
})
})
$inc 연산자는 해당 속성의 값 부분만큼 증가시킨다. 따라서 post collection의 게시물이 하나씩 등록 될 때마다 counter collection의 totalPost값 또한 1씩 증가한다.
* delete
1. method-override 라이브러리의 도움을 받는다
2. AJAX로 DELETE 요청을 날린다
3. 그냥 POST요청을 날려서 DELETE 작업을 수행한다
// (server.js)
app.delete('/delete', function(요청, 응답){
요청.body._id = parseInt(요청.body._id)
db.collection('post').deleteOne(요청.body, function(에러, 결과){
console.log('삭제완료')
})
응답.send('삭제완료')
});
삭제: deleteOne(삭제원하는 데이터이름, function(){} )
삭제하려고 보낸 데이터가 문자열 형태로 올 수도 있으니 형변환을 해주어야한다.
* detail
app.get('/detail/:id', function(요청, 응답){
db.collection('post').findOne({ _id : 요청.params.id }, function(에러, 결과){
응답.render('detail.ejs', {data : 결과} )
})
});
파라미터에 (:) 기호를 붙여주면 detail/뒤에 아무 문자열이나 입력할 수 있다.
request.params.id는 사용자가 URL에 입력한 :id 값을 의미한다.
서버에서의 response
app.get('/어쩌구', function(요청, 응답){
응답.send('<p>some html</p>')
응답.status(404).send('Sorry, we cannot find that!')
응답.sendFile('/uploads/logo.png')
응답.render('list.ejs', { ejs에 보낼 데이터 })
응답.json(제이슨데이터)
});
페이지 분할
- include
<body>
...
<%- include('파일.html') %>
...
</body>
해당하는 html파일을 EJS파일에 include 형식으로 포함 시킬 수 있다. 주로 중복되는 파일을 따로 관리할 때 사용한다. (html 파일은 불가 하려면 jQuery 사용 해야함, EJS파일에 가능)
- CSS 파일 넣을 때
<head>
<link href="/public/님들이만든CSS파일.css" rel="stylesheet">
</head>
// (server.js)
app.use('/public', express.static('public'))
추가적으로 node에도 등록해야한다.
'NodeJs' 카테고리의 다른 글
[Node.js] chap.3 (0) | 2021.12.27 |
---|---|
[Node.js] chap.1 (0) | 2021.12.20 |