[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

+ Recent posts