[유튜브 강의] Node js 와 mongoDB, Heroku(헤로쿠,히로쿠)로 만드는 다이어리앱 (서버편) - 3

2020. 3. 7. 14:30[유튜브 강의]- 센치한 개발자/[Server] 잡다한 강의 - 진행중

728x90

 

 

 

▶︎ 센치한 개발자 유튜브 구독하기 : https://www.youtube.com/channel/UCvb9oqG4CtZ5H4m_NSD1GYA?sub_confirmation=1

 

[ Node js 와 mongoDB, Heroku(헤로쿠)로 만드는 다이어리앱 (서버편) 목차 ]

1. Node js 와 mongoDB, Heroku(헤로쿠)로 만드는 다이어리앱 (서버편) - 1

2. Node js 와 mongoDB, Heroku(헤로쿠)로 만드는 다이어리앱 (서버편) - 2

3. Node js 와 mongoDB, Heroku(헤로쿠)로 만드는 다이어리앱 (서버편) - 3

4. Node js 와 mongoDB, Heroku(헤로쿠)로 만드는 다이어리앱 (서버편) - 4 (서버편 완결)

 

 

1,2편에 이어서 다이어리 내용을 "읽기(조회), 쓰기(추가), 수정, 삭제"(일명 CRUD) 하기 위해 Rest API용 로직으로 좀 더 깔끔하게 바꿔보겠습니다. 한 곳에 소스가 너무 많아지면 복잡해져서 관리도 힘들고 현재로서는 목적에도 부합하지 않기 때문이죠...

우리는 이 과정을 "라우팅(route, routing)" 과정이라고 합니다.

 

*. Rest API 는 또 뭐야! 새로운 개념 자꾸 들이대지 마라고!

: 간단히 말하면 www 웹에서 api 통신을 할때의 규약으로 좀 더 명확하게 깔끔하게 구분이 가능토록 만들어서 추후에 범용성이나 확장성에도 유용하게 하려는 구조로 만드는 API 입니다.

 

*. API (Application Programming Interface)는 또 뭔데..

:  쉽게 리모콘을 생각해주세요.

(저희집은 음성으로 하는데요라고 하신다면 그 리모콘이 TV안에 들어가있다고 보시면 됩니다..)

볼륨업, 다운 버튼을 TV에다 대고 누르면 동작하죠?

"리모콘을 볼륨을 올렸다." 라는 명령이 곧 "TV를 제어하는 API"라고 보시면 됩니다..

리모콘은 곧 TV를 제어하는 API의 집합체, 실물, 찐(?) 물건인 것이죠.

볼륨을 올리는 동작을 쉽게 할 수 있게 리모콘이라는 API 물건(?)을 제공하고 있는 거하고 생각해주세요.

 

기존까지는 첫 페이지에 모든 내용이 들어가있어서 이제는 화면은 없고 통신을 목적으로 하는 API용 로직이 필요합니다.

 

그래서 크게 아래와 같은 순서로 변경하려고 합니다.

(1) API 설계
(2) API용 파일 분리 구성 
(3) API 호출

 

(1) API 설계

 1) 설계

  • 특정한 URL 주소로 API 접속을 요청하면 그 주소에 따라 각각 다이어리 읽기, 쓰기, 수정, 삭제가 되게 할 것인데, 그 방식(Method라고 합니다)은 RestApi에서 사용하는 방식으로 표현합니다.

그래서, CRUD 로직은 다음과 같이 구성할 생각입니다.

URL 방식(Method) 용도
/api/diary GET 모든 다이어리 조회 (1건 이상)
/api/diary/:diary_id GET 특정 id 값으로 다이어리 조회 (1건)
/api/diary/ POST 다이어리 데이터 추가
/api/diary/:diary_id PUT 다이어리 데이터 수정
/api/diary/:diary_id DELETE 다이어리 데이터 삭제

*. /api/diary : 다이어리 공통 api 경로입니다.

(2) API 파일 분리 구성

*. 어떻게 라우터와 DB모델 스키마를 분리할 지 디렉토리와 파일 구조를 미리 살펴보면 다음 구조와 같습니다.

 

 1) 다이어리 모델 스키마 분리

  • index.js에 들어가있던 모델 부분을 분리할 예정입니다.
  •  프로젝트 최상위에 model 디렉토리를 만들고 diary.js 파일 생성하여 넣습니다

 

  • 해당 모델 파일(/model/diary.js)을 다음과 같이 구성합니다.
const mongoose = require('mongoose');

//모델 설정
var Schema = mongoose.Schema;

//{ date : "2020131", title : "test2", imgList : "",  content : "아아2" }
var dairySchema = new Schema(
    {  date : String, title : String, imgList : String,  content : String}
);

module.exports = mongoose.model('dairy', dairySchema, 'dairy');

 

2) 라우터 분리 :

  • api만 처리하는 별도의 diary.js 파일을 만들기 (일명 '라우터') 
  • 최상위에 routes 디렉토리를 만들고 diary.js 파일 생성하여 넣습니다 
  • 주의! 아까는 모델 스키마라서 model 디렉토리였습니다!

   

  - 해당 API 라우터파일(/routes/diary.js)을 실제 모델 스키마 (/model/diary.js)를 기반으로 아래와 같이 바꿉니다.

var express = require('express');
var data = require('../model/diary');                       //다이어리 모델 스키마를 가져온다
var bodyParser = require('body-parser');                    //body의 json을 파싱해주는 모듈
var dateFormat = require('dateformat');                     //날짜형식을 원하는 형태로 바꿔주는 모듈
var empty = require('is-empty');                            //빈값 체크 모듈 *.주의:0도 empty로 판단함
const stringify = require("json-stringify-pretty-compact"); //json 값을 문자열로 (보기좋게)변환해주는 모듈

var router = express.Router();

router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());



//전체 데이터를 불러와서 항목별로 보기 : 실제 호출주소 http://~~/api/diary/
router.get('/', function (req, res) {

    data.find(function(error, dairy){

        var resultData = "";
        
        //에러가 없고, 결과값이 있다면
        if(!error && !empty(dairy)){
            resultData = dairy;
            // resultData = stringify(dairy);
        }

        res.json({result: empty(error), error:error, data:resultData});
    });

});

//id 기반으로 조회하여 데이터를 1건 불러오기 : 실제 호출주소 http://~~/api/diary/id값
router.get('/:id', function (req, res) {

    data.findOne({_id:req.params.id}, function(error, dairy){

        var resultData = "";
        if(!error && !empty(dairy)){
            resultData = dairy;
        }

        res.json({result: empty(error), error:error, data:resultData});
    });
});

//데이터를 추가하기 : 실제 호출주소 http://~~/api/diary/ + body데이터 
router.post('/', function (req, res) {

    var title = req.body.title;
    var content = req.body.content;

    if(!empty(title) && !empty(content)) {
        var diaryData = new data();
        diaryData.title = title;
        diaryData.content = content;
        var now = new Date();
        diaryData.date = dateFormat(now, "yyyymmdd");
        diaryData.imgList = "";

        //콘솔창을 통해서 로그를 확인해볼 수 있다
        console.log("dairy content diaryData::" + diaryData);

        diaryData.save(function(error, resultData){
            res.json({result: empty(error), error:error, data:resultData});
        });
    }
    else {
        res.json({result: false, error:null, data:null});
    }

});

//id로 데이터를 찾아서 수정 : 실제 호출주소 http://~~/api/diary/ + body데이터 
router.put('/:id', function (req, res) {

    var title = req.body.title;
    var content = req.body.content;
    const id = req.params.id;

    if(!empty(id)) {

        data.findOneAndUpdate({_id: id}, {$set:
                    { title: title, content: content }
                }, {returnNewDocument: true}, (error, doc) => {
            res.json({result: !error, error:error});
        });
    }
    else {
        res.json({result: false, error:null, data:null});
    }

});

//id로 찾아서 삭제 : 실제 호출주소 http://~~/api/diary/id값 
router.delete('/:id', function (req, res) {
    const id = req.params.id;
    if(!empty(id)) {
        data.remove({_id: id}, function(error, resultData){
            res.json({result: empty(error), error:error, data:resultData});
        });
    }
    else {
        res.json({result: false, error:null, data:null});
    }
});

module.exports = router;

 

 

3) index.js에 2)에서 분리한 라우터 모듈(router) 등록 

  • 이를 통해서 서버가 시작되면 API를 받을 준비를 시켜줍니다.
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000
const router = require("./routes/dairy"); //라우터 모듈 등록 (라우터 모듈안에 다이어리 스키마 모듈을 불러오고 있으므로 아래와 같이 라우터만!

var app = express();
app
    .use(express.static(path.join(__dirname, 'public')))
    .use('/api/diary', router)
    .set('views', path.join(__dirname, 'views'))
    .set('view engine', 'ejs')
    .get('/', (req, res) => res.render('pages/index'))
    .listen(PORT, () => console.log(`Listening on ${ PORT }`))

 

(3) API 호출

  *. 빌드에 필요한 npm 모듈 미리 설치 

//콘솔창에서..
npm install dateformat

npm install is-empty

npm install json-stringify-pretty-compact

//귀찮으면 package.json 파일의 dependencies 부분을 찾아 
//추가, 수정 (dateformat, is-empty, json-stringify-pretty-compact)
"dependencies": {
    "body-parser": "^1.19.0",
    "dateformat": "^3.0.3",
    "ejs": "^2.5.6",
    "express": "^4.15.2",
    "is-empty": "^1.2.0",
    "json-stringify-pretty-compact": "^2.0.0",
    "mongoose": "5.9.2"
}

 

 * 편하게 데이터를 확인해보면서 API를 테스트하려면 PostMan 프로그램을 설치하세요~ (사용법은 방송에서 알려드립니다) 

 

 이제 실제로 postman 을 통해 API를 로컬에서 호출(body, content-type 등을 설정하여)해보면 아래와 같이 나올 수 있습니다. 

 

 

[ 다음편 ] : 헤로쿠 서버에 소스배포 (드디어 어디서든 접속 가능해집니다!)  

 

728x90