[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

[WEB] HTTP와 서블릿(Servlet) 요청(Request), 응답(Response)

 

 

클라이언트와 서버간에 인터넷 통신을 하는 것을 웹 통신이라고 하며, 이러한 웹은 HTTP기반으로 이루어진다. HTTP는 HTML, TEXT 등과 IMAGE, 음성, 영상 파일 등의 다양한 형태의 데이터를 전송할 수 있다.

 

이러한 HTTP를 기반으로 하는 서버에는 WEB서버와 WAS(Web Application Server)서버가 있는데 이 서버의 특징은 아래와 같다.

 

 

- 웹 서버(Web Server)

  • HTTP 기반으로 동작한다.
  • 정적 리소스(HTML, CSS, JS, 이미지, 사진, 영상 등) 제공
  • 예로 APACHE, NGINX 등이 있다.

 

- 웹 애플리케이션 서버(WAS - Web Application Server)

  • HTTP 기반으로 동작한다.
  • 웹 서버 기능을 포함한다. (정적 리소스 제공 가능)
  • 프로그래밍 코드를 실행해서 애플리케이션 로직을 수행한다.
  • 동적 리소스(HTML, HTTP API, 서블릿, JSP 등) 수행
  • 예로 Tomcat, Jetty, Undertow 등이 있다.

 

웹 시스템의 구성

 

기본적으로 웹 시스템의 구성은 정적 리소스는 WEB서버에서 동적(애플리케이션) 리소스는 WAS에서 관리하며 로직 등을 통해 DB 서버와 데이터를 송, 수신 한다.

 

여기서 Client가 WAS와 통신을 할 때, HTTP 메세지를 기반으로 통신한다. HTTP의 메세지는 기본적으로 시작 라인(start-line)과 헤더(header), 메세지 바디(message body), 헤더와 메세지 바디 사이에 공백라인(empty line, CRLF)로 구성된다.

 

- HTTP 요청메세지 시작 라인

  • HTTP 메서드(GET, POST, PUT, PATCH, DELETE)
  • 요청 대상 (/path[?query&parameter=value])
  • HTTP 버전

 

- HTTP 응답메세지 시작 라인

  • HTTP 버전
  • HTTP 상태코드 (200: 성공, 400: 클라이언트 오류, 500: 서버 오류)

 

- HTTP 메세지 헤더

  • HTTP 전송에 필요한 모든 부가정보 (메세지 바디의 내용, 크기, 압축, 인증, 요청 클라이언트 정보 등)

 

- HTTP 메세지 바디

  • 실제 전송할 데이터 (HTML, 이미지, 영상, JSON 등 byte로 표현 할 수 있는 모든 데이터 전송)

 

 

Client와 Server가 통신하면서 수행하려고 했던 의미있는 비즈니스 로직을 제외한 TCP / 소켓 연결, HTTP 메세지 파싱, 서버 기능 프로세스 실행 등 서버해서 설정해야 할 처리들이 있는데 이 설정들은 비슷하게 반복적이고 양도 많기 때문에 서블릿(Servlet)을 사용한다.

 

서블릿(Servlet)은 Client가 Server에 HTTP를 통한 요청과 응답 정보를 편리하게 사용하고 제공 받을 수 있게 해준다. 서블릿을 이용하면 Request와 Response 객체를 사용 할 수 있는데 이 객체를 통하여 HTTP 요청, HTTP 응답 메세지를 편하게 가져오고 입력할 수 있다.

 

 

@WebServlet(name = "testServlet", urlPatterns = "/test")
public class TestServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       // 비즈니스 로직
    }

위와 같은 서블릿을 사용하게 되면 Client와 Server의 통신간에 설정해야 할 처리들을 알아서 설정해주고 의미있는 비즈니스 로직 부분만을 구현 할 수 있다.

 

@WebServlet에서 해당 urlPattern의 URL이 호출되면 service메서드의 비즈니스 로직 부분이 실행되고 HttpServletRequest 객체를 통해 HTTP 요청 정보를 사용 할 수 있으며 HttpServletResponse 객체를 통해 HTTP 응답 정보를 제공 할 수 있다.

 

+ Recent posts