2018년 4월 4일 수요일

Node.js - 스터디 2주차 - OrientDB

https://opentutorials.org/course/2136/

생활코딩 강의를 이용해 진행하는 스터디 2주차.

4/5(목) :: 20강 'OrientDB 소개 및 기본 사용법' 부터 21강 'OrientDB로 웹애플리케이션 구현' 까지.

강의에서 사용하는 OrientDB는 처음 알게된 DB인데 내용이 꽤나 흥미롭다. MongoDB를 사용해본 적이 없어서 MongoDB로 수업이 진행 되었으면 더 좋았겠지만..

OrientDB

OrientDB는 NoSQL(Not Only SQL) 이면서 GraphDB이다. NoSQL 솔루션은 많이 알려졌듯이 RDB에 비해 확장성, 스키마 유연성 측면에서 강점이 있다.

GraphDB?

그래프 데이터베이스는 그래프 이론에 토대를 둔 일종의 NoSQL 데이터베이스이다. 객체나 노드로 불리는 데이터 포인트를 플롯하고, 이들의 관계를 선으로 연결해 데이터의 복잡한 관계를 더 쉽고 빠르게 파악하게 해준다.

1) 관계형 데이터베이스는 데이터를 열과 행으로 저장한다.
2) NoSQL 데이터베이스는 많은 비정형 데이터를 저장한다.
3) 그래프 데이터베이스는 더 나아가 데이터 포인트를 연결, 데이터 네트워크를 구축한다.

무엇이 더 좋냐 나쁘냐의 문제는 아니고, 해결하려는 문제에 더 적합한 데이터베이스의 형태가 있다고 할 수 있겠다. 어쨌든 OrientDB에서 제공하는 그래프 화면은 아래와 같다.


OrientDB는 MongoDB와 같이 도큐먼트 베이스로 동작하지만 Object-Oriented 특성을 추가로 갖는 특징이 있고, RDB에서 사용하던 일반적인 SQL 구문을 이용해 데이터를 쉽게 찾을 수 있는 등의 이점이 있다.

OrientDB의 설치와 초기 설정

Enterprise는 돈을 지불해야 사용할 수 있는 것 같고, Community Edition을 내려받으면 된다. (*OrientDB는 Java로 만들어진 데이터베이스 엔진이기 때문에 사전에 Java가 설치되어 있어야 한다.) 설치방법은 매우 간단하다. Windows에서도 그냥 압축파일 형태로 되어있고, 아무데서나 압축을 해제한 후 생성된 bin 폴더의 server.bat를 시작하면 데이터베이스 서비스가 시작된다. (server.bat 파일을 열어보면 힙 메모리 크기, 동작 머신-x64/x86 등을 지정할 수 있으니 필요하면 건드리자.)

server.bat를 처음 시작하면 password를 물어보는데 root password에 해당되니 기억해두자. 서비스가 시작되고 나서 웹 브라우저를 이용해 localhost의 2480 포트로 접속하면 데이터베이스 관리자 화면을 확인할 수 있다. 여기서 데이터베이스를 생성하거나 스키마를 지정해줄 수 있다. 참고로 데이터베이스의 기본 접속 포트는 2424이고, 데이터베이스 GUI 관리자 화면의 접속 포트는 2480이 기본값이다.



Node.js에서 OrientDB 사용하기.


Node.js에서 OrientDB를 사용하려면 orientjs라 하는 모듈이 설치되어 있어야 한다.
npm install orientjs --save

사용 흐름과 쿼리 방식은 아래 스크린 샷과 같은데. 크게 어렵거나 하지 않아서. 사진으로 대체한다.


insert 후엔 insert 결과를 반환하는데 여기에서 @rid를 얻을 수 있다.
update/delete후엔 영향을 받은 row 수가 ['1'] 과 같은 형태로 반환된다.

OrientDB로 웹애플리케이션 구현

파일 기반으로 작성된 웹애플리케이션을 OrientDB로 변환하는 과정에 대한 내용이다. 아래와 같이 강사님처럼 API 지도를 만들어주면 전체적인 흐름을 파악하기에 좋다.

get('topic/') : view.jade
get('topic/:id') : view.jade
get('topic/add') : add.jade
ㄴpost('topic/add')
ㄴget('topic/:id')
get('topic/:id/edit') : edit.jade
ㄴpost('topic/:id/edit')
ㄴget('topic/:id')
get('topic/:id/delete') : delete.jade
ㄴpost('topic/:id/delete')
ㄴget('topic/')

자료를 OrientDB로 부터 읽어와 화면에 전달하는 로직은 크게 어렵지 않지만 주의할 점이 몇가지 있다.

1) OrientDB의 식별자는 '@rid'란 이름을 갖는데, jade에서 object.@rid와 같이 표현할 경우 에러를 뱉는다. 따라서 object['@rid']와 같은 표현으로 식별값에 접근해야 한다.

2) @rid의 값은 '#숫자:숫자' 형식으로 되어있는데, @rid를 이용해 링크 URL 등을 생성할 경우 '#', ':' 문자에 대한 처리를 해주어야 한다. '#'의 경우 페이지의 특정 위치로 스크롤하는데 쓰이는 특수 기호이기 때문이다. 강의에서는 encodeURIComponent(topic['@rid']) 와 같은 처리를 통해 @rid 값을 인코딩해 서버로 전달되게끔 구현하였다.

view.jade의 풀 소스는 다음과 같다. if / else 구문을 jade에 바로 사용할 수 있는 부분이 반갑다. '|'는 태그 없이 문자열을 출력하고 싶을 때 사용하면 된다.

doctype html
html
  head
    meta(charset='utf-8')
  body
    h1
      a(href='/topic/') Server Side JavaScript
    ul
      each topic in topics
        li
          - rid = encodeURIComponent(topic['@rid'])
          a(href='/topic/' + rid)= topic.title
    article
      if topic
        h2= topic.title
        = topic.description
      else
        h2 Welcome
        | This is server side javascript tutorial.
      br
    div
      a(href='/topic/new') new

이에 대한 핸들링 함수는 아래와 같다. 지저분해 보이지만 일단 동작하는게 우선.


조회 부분을 구현하고나면 다음. 추가 / 편집 / 삭제은 비교적 편하게 구현할 수 있다.
개발 과정에서 잘 모르는 건 console이든 browser로 보내든 output을 찍고 보는 습관.

추가 - INSERT

app.post('/topic/add', function(req, res) {
  var title = req.body.title;
  var description = req.body.description;
  var author = req.body.author;
  var sql = 'INSERT INTO topic (title, description, author) VALUES (:title, :description, :author)';
  db.query(sql, {
    params: {
      title: title,
      description: description,
      author: author
    }
  }).then(function (results) {
    res.redirect('/topic/' + encodeURIComponent(results[0]['@rid']));
  });
});

편집 - UPDATE

편집 기능을 선택하면. 조회 로직과 유사하게 선택된 아이템의 값을 가져와 화면에 뿌려주는 부분을 구현하면 된다. 그리고나서 action의 URI를 edit로 지정하고, edit POST 요청에 대한 서비스를 구현하면 된다.

jade
    article
      - rid = encodeURIComponent(topic['@rid'])
      form(action='/topic/' + rid + '/edit' method='post')
        p
          input(type='text' name='title' placeholder='title' value=topic.title)
        p
          textarea(name='description' placeholder='description')
            =topic.description
        p
          input(type='text' name='author' placeholder='author' value=topic.author)
        p
          input(type='submit')

js
app.post('/topic/:id/edit', function (req, res) {
  var sql = 'UPDATE topic SET title=:t, description=:d, author=:a WHERE @rid=:id';
  var id = req.params.id;
  var title = req.body.title;
  var desc = req.body.description;
  var author = req.body.author;
  db.query(sql, {
    params: {
      id: id,
      t: title,
      d: desc,
      a: author
    }
  }).then(function(topics) {
    res.redirect('/topic/' + encodeURIComponent(id));
  });
});

삭제 - DELETE

특별한 내용은 없지만 주의할 점이 있다. 데이터에 변경을 가하는 INSERT / UPDATE / DELETE 등의 작업에 대해 GET 메서드를 사용하지 않는 것과 더불어 그러한 기능을 수행하는 태그에 <a> 태그를 쓰지 않도록 한다. <a> 태그를 사용하는 경우에 크롤링 엔진 등에 의해 해당 기능이 자동 실행될 수 있어 예기치 않게 데이터에 손상을 입힐 수 있기 때문이다.

jade
    article
      h1= 'Delete? ' + topic.title
      - rid = encodeURIComponent(topic['@rid'])
      form(action='/topic/' + rid + '/delete' method='post')
        p
          input(type='submit' value='YES')
      a(href='/topic/' + rid) No

js
app.post('/topic/:id/delete', function (req, res) {
  var sql = 'DELETE FROM topic WHERE @rid=:id';
  var id = req.params.id;
  db.query(sql, { params: { id: id }}).then(function(topics) {
    res.redirect('/topic/');
  });
});


댓글 없음:

댓글 쓰기