프로그래밍/JS, Node.js

(1) Node.js로 RESTful API 만들기 - POST편

Lou Park 2017. 1. 24. 01:43

글 목차

현재글 >> (1) Node.js로 RESTful API 만들기 - POST편

(2) Node.js로 RESTful API 만들기 - GET편

(3) Node.js로 RESTful API 만들기 - PUT편

(4) Node.js로 RESTful API 만들기 - DELETE편

(5RESTful API 활용하기 - 웹편 (작성중)

(6) RESTful API 활용하기 - 안드로이드 앱편 (작성중)

RESTful API에 관하여

Node.js를 세팅하는 과정은 복잡하므로 생략!

시작하기에 앞서서, 간단하게 REST에서 사용하는 메서드 4가지에 대해서 소개하겠다.


POST: 생성 (create)

GET: 조회 (select)

PUT: 수정 (update)

DELETE: 삭제 (delete)


CRUD에 해당되는 것이 저것들인데,

이 글에서는 위 4가지 메서드를 Node.js를 통해 API 서버를 구현해보고

웹과 안드로이드 앱에서 통신 해볼 것이다.


DB 세팅

단순함을 극대화 시키기 위하여, 데이터 베이스는 다음과 같이 설계했다.


 create table myGames (

    -> id int auto_increment,

    -> title varchar(255) not null,

    -> primary key (id)

    -> );


myGames라는 테이블 안에 게임타이틀을 넣을 수 있도록 했다.


프로젝트 파일 구조


파일 구조는 위 사진과 같다.

이제 각각의 js 파일들을 뜯어 보도록 하겠다.


app.js

app.js는 메인 파일이다. 그래서 각종 라이브러리, 미들웨어들을 정의하고, 라우터를 불러온다.

주석에 왠만한건 다 적혀있다! (이해가지 않는 부분은 댓글로 ~)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var express = require("express");
var mysql = require("mysql");
var bodyParser = require("body-parser");
var config = require("./config"); // config.js
var app = express();
 
// bodyParser는 미들웨어이기 때문에 라우터 보다 항상 위에 있도록 해야함
app.use(bodyParser.json());     
// parse application/x-www-form-urlencoded 
app.use(bodyParser.urlencoded({extended: false}));
 
// Mysql DB pool 생성
var pool = mysql.createPool({
            // config.js에 있는 정보를 바탕으로 연결
            host: config.mysql.host,
            port: config.mysql.port,
            user: config.mysql.username,
            password: config.mysql.password,
            database: config.mysql.db,
            connectionLimit:20,
            waitForConnections:false
        });
 
// Main
app.listen(config.port, function() {
    console.log("Server listening on port %d", config.port);
});
 
// Router
// 기본으로 index.js를 찾기 때문에 
// require("./routes/index.js")라고 명시해주지 않았음
var routes = require("./routes")(app, pool);
cs


config.js

앱 설정이 바뀌었을때 일일이 코드마다 그 부분을 수정하기란 골치아픈 일이기 때문에 config.js에 모든 설정을 다 모아 놓았다.  

이것은 단순히 예제이므로 모든 항목에서 자신에게 맞는 세팅을 해놓고 시작하면 좋다.

env파일에 config를 모아 놓는 것을 많이 보았는데, 아직 초보자라 env를 잘 이해하지는 못하겠다 ㅠㅠ


1
2
3
4
5
6
7
8
9
10
11
12
var config = {
    port: 3000,
    mysql: {
        host: "localhost",
        port: 3306,
        db: "testdb",
        username: "root",
        password: "*******",
    }
}
 
module.exports = config;
cs


/routes/index.js

본격적으로 post 메소드가 나오기 시작했다!

app.js에서 만든 app과 pool을 인자로 받아서 사용한다.

"http://localhost:3000/games" 주소로 POST 요청을 보내면 데이터 베이스에 새로운 레코드를 추가한다.


나는 코드의 반복을 없애기 위해 returnResult라는 함수를 만들어 사용했는데, 

별로인것 같다면 쓰지 않아도 된다.


원래는 async를 쓰지 않고 올렸으나 수정을 했다.

async.waterfall은 첫번째 인자인 [] 안에 있는 함수들을 순차적으로 실행한 후, 마지막으로 두번째 인자 함수를 실행한다.

도중에 에러가 발생하면 곧바로 두번째 함수를 실행한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
var async = require("async");
var mysql = require("mysql");

module.exports = function(app, pool) {
    // >> POST
    app.post("/games"function(req, res) {
        var result = {};
        var title = null;
        async.waterfall([
        function(callback) {
            title = mysql.escape(req.body.title);
            callback();
        },
        function(callback) {
            if (title == undefined) {
                callback(new Error("Title is empty."));
            } else {
                // db에 연결하여 sql 수행
                pool.getConnection(function(err, conn) {
                    // title 정보를 DB에 넣기 위한 SQL문 준비
                    var sql = "INSERT INTO myGames (title) VALUES (" + title + ");";
                    console.log("SQL: " + sql);
                    conn.query(sql, function(err) {
                        if (err) {
                            // err가 떠도 conn은 release() 꼭 해주어야한다.
                            conn.release();
                            callback(err);
                        } else {
                            conn.release();
                            callback();
                        }
                    });
                });
            }
        }],
        function(err) {
            result = returnResult(err, res)
            result.status = res.statusCode;
            res.send(result);
        });
    });
}
 
var returnResult = function(err, res) {
    // 결과를 눈으로 보기 쉽게하기 위해 result 객체 생성
    var result = {};
    if (err) {
        res.status(400);
        result.message = err.stack;
    } else {
        res.status(200);
        result.message = "Success";
    }
    result.status = res.statusCode;
    res.send(result);
}
 
cs


테스트

Postman을 이용하여 직접 "http://localhost:3000/games"에 POST 요청을 주면 어떻게 될까?

우선 터미널 또는 명령프롬프트를 이용해 노드 앱을 실행한다.



"Server listening on blablabla"가 뜨면서 서버가 실행되었다.

이제 Postman을 실행시켜 주소를 올바르게 적고, POST 메소드로 JSON 데이터를 전달 해 보자.

아래와 같이 설정하고 Send 버튼을 누르면 된다.


첫번째로 추가할 게임은 오버워치(Overwatch)다!


POST 요청이 제대로 완료된걸까?

제대로 완료되었으면 코딩한대로 페이지에는 아래와 같이 표시된다.

그리고 Mysql에 접속해서 myGames 테이블 상황을 확인해보면

오버워치가 성공적으로 들어가 있는 것을 볼 수 있다.



실패할 경우는 그럼 어떨까??

일부러 title대신 titlle이라고 오타를 내어 title 값을 undefined로 줘 보았다. (이번 게임은 GTA~)




어마 무시한 에러가 뜬 것 처럼 보인다. 하지만 코드에서 명시해준 대로 Title이 비었다는 메세지가 보인다!

status는 400이다. 만약 라인단위로 보고싶지 않고 단순히 에러만 보고 싶다면

index.js의 29번째 라인에 err.stack 대신 err.message를 쓰면 Title is Empty정도만 보이게 될 것이다.


이것으로 POST 메서드 구현이 끝났다.

세팅을 여기서 다 했으니 나머지 메서드는 더 쉽게 구현할 수 있을 것이다.

다음글에서 마저 하도록 하겠다.