2-5. 데이터 생성과 조회

이제 데이터베이스를 연동하여 books API 의 기능을 구현해보겠습니다.

먼저, books.controller.js 파일의 상단에 아까 우리가 만든 모델을 불러와주세요.

src/api/books/books.controller.js - 상단

const Book = require('models/book');

데이터 생성

create 함수부터 구현을 해보도록 하겠습니다.

src/api/books/books.contriller.js - create

exports.create = async (ctx) => {
    // request body 에서 값들을 추출합니다
    const { 
        title, 
        authors, 
        publishedDate, 
        price, 
        tags 
    } = ctx.request.body;

    // Book 인스턴스를 생성합니다
    const book = new Book({
        title, 
        authors,
        publishedDate,
        price,
        tags
    });

    // 만들어진 Book 인스턴스를, 이렇게 수정 할 수도 있습니다.
    // book.title = title;

    //.save() 함수를 실행하면 이 때 데이터베이스에 실제로 데이터를 작성합니다.
    // Promise 를 반환합니다.
    try {
        await book.save();
    } catch(e) {
        // HTTP 상태 500 와 Internal Error 라는 메시지를 반환하고, 
        // 에러를 기록합니다.
        return ctx.throw(500, e);
    }

    // 저장한 결과를 반환합니다.
    ctx.body = book;
};

코드를 작성하고, 저장을 한 다음에 Postman 으로 테스팅을 해보겠습니다.

POST 메소드로 http://localhost:4000/api/books 에 Request Body 는 JSON 형식으로 다음과 같이 입력하여 Send 를 눌러보세요.

{
    "title": "React.js Tutorials",
    "publishedDate": "2017-07-13",
    "authors": [
        {
            "name": "velopert",
            "email": "public.velopert@gmail.com"
        },
        {
            "name": "nakim",
            "email": "nakim@nakim.com"
        }
    ],
    "tags": ["react.js", "node.js"],
    "price": 100
}

다음과 같이 나타나면 잘 된 것입니다. 이제, Send 를 5번정도 눌러보면서 (원한다면 내용도 조금 바꿔보세요) _id 값이 바뀌는것을 확인해보세요.

그 다음엔, Robomongo 를 열어서 데이터베이스에 접속 후, 다음과 같이 데이터를 조회해보세요.

데이터 조회

이제 여러개의 데이터 목록을 조회해보겠습니다. 데이터를 조회 할 때는 .find() 를 사용합니다.

src/api/books/books.controller.js - list

exports.list = async (ctx) => {
    // 변수를 미리 만들어줍니다. 
    // (let 이나 const 는 scope 가 블록단위이기 때문에, try 바깥에 선언을 해줍니다)

    let books;

    try {
        // 데이터를 조회합니다. 
        // .exec() 를 뒤에 붙여줘야 실제로 데이터베이스에 요청이 됩니다.
        // 반환값은 Promise 이므로 await 을 사용 할 수 있습니다.
        books = await Book.find().exec();
    } catch (e) {
        return ctx.throw(500, e);
    }

    ctx.body = books;
};

아까 코드보단 간단하지요? 이제 한번 Postman 으로 GET http://localhost:4000/api/books 에 요청을 해보세요.

[
    {
        "_id": "594fd27d7b8031d36ef0de03",
        "title": "React.js Tutorials5",
        "publishedDate": "2017-07-13T00:00:00.000Z",
        "price": 100,
        "__v": 0,
        "createdAt": "2017-06-25T15:10:53.654Z",
        "tags": [
            "react.js",
            "node.js"
        ],
        "authors": [
            {
                "name": "velopert",
                "email": "public.velopert@gmail.com",
                "_id": "594fd27d7b8031d36ef0de04"
            },
            {
                "name": "nakim",
                "email": "nakim@nakim.com",
                "_id": "594fd27d7b8031d36ef0de05"
            }
        ]
    },
    (...)
]

위와 같이 모든 데이터가 나타나게 됩니다.

이번엔, 데이터를 _id의 역순으로 정렬하고 3개만 보여주도록 제한을 주겠습니다. 즉, 최근 생성된 3개만 보여준다는 의미이지요.

src/api/books/books.controller.js - list

exports.list = async (ctx) => {
    // 변수를 미리 만들어줍니다. 
    // (let 이나 const 는 scope 가 블록단위이기 때문에, try 바깥에 선언을 해줍니다)

    let books;

    try {
        // 데이터를 조회합니다. 
        // .exec() 를 뒤에 붙여줘야 실제로 데이터베이스에 요청이 됩니다.
        // 반환값은 Promise 이므로 await 을 사용 할 수 있습니다.
        books = await Book.find()
            .sort({_id: -1}) // _id 의 역순으로 정렬합니다
            .limit(3) // 3개반 보여지도록 정렬합니다
            .exec(); // 데이터를 서버에 요청합니다.
    } catch (e) {
        return ctx.throw(500, e);
    }

    ctx.body = books;
};

이렇게, 데이터를 요청하는것을 쿼리라고 부릅니다. 앞으로 다양한 종류의 쿼리를 코드를 작성해가면서 배울 것 입니다. 만약에 미리 어떤것들이 있는지 알고싶다면 공식문서의 queries 페이지를 참조하세요.

단일 데이터 조회

위 부분에서는 데이터의 목록을 조회하는 방법을 알아보았는데요, 이번엔 특정 아이디를 가진 데이터를 조회하는것을 알아보겠습니다.

특정 아이디를 가진 데이터를 조회 할 때는, .findByOne 을 사용합니다.

get 이라는 함수를 만들어서 다음과 같이 코드를 작성하세요.

src/api/books/books.controller.js - get

exports.get = async (ctx) => {
    const { id } = ctx.params; // URL 파라미터에서 id 값을 읽어옵니다.

    let book;

    try {
        book = await Book.findById(id).exec();
    } catch (e) {
        return ctx.throw(500, e);
    }

    if(!book) {
        // 존재하지 않으면
        ctx.status = 404;
        ctx.body = { message: 'book not found' };
        return;
    }

    ctx.body = book;
};

데이터가 존재하지 않으면 HTTP 상태 404를 반환합니다.

그 다음엔 /:id 라우트에 방금 만든 get 함수를 전달하세요.

src/api/books/index.js

const Router = require('koa-router');

const books = new Router();
const booksCtrl = require('./books.controller');

books.get('/', booksCtrl.list);
books.get('/:id', booksCtrl.get);
books.post('/', booksCtrl.create);
books.delete('/', booksCtrl.delete);
books.put('/', booksCtrl.replace);
books.patch('/', booksCtrl.update);

module.exports = books;

이렇게 API 를 만들고 나면, 아까 목록에 나타났었던 id 를 주소 뒤에 붙여넣으세요. GET http://localhost:4000/api/books/594fd2917b8031d36ef0de0c 이런식으로 요청하면, 주어진 id 로 데이터 하나를 조회하게 됩니다.

그리고 맨 마지막 문자를 다른 값으로 변형시켜보세요. 594fd2917b8031d36ef0de0f 이런식으로 말이죠. 404 가 나타나게 됩니다. 하지만, 아예 문자 하나를 지워버리거나 하나를 더 넣어버리면 Internal Error 가 나타날것입니다.

id 를 파라미터로 받을때는, 에러를 처리해주거나, 사전에 id 검증작업을 거쳐야합니다. id 검증작업은 나중에 해보도록하고, 이번엔 에러를 처리해주는 방식으로 코드를 고치겠습니다.

src/api/books/books.controller.js - get

exports.get = async (ctx) => {
    const { id } = ctx.params; // URL 파라미터에서 id 값을 읽어옵니다.

    let book;

    try {
        book = await Book.findById(id).exec();
    } catch (e) {
        if(e.name === 'CastError') {
            ctx.status = 400;
            return;
        }
        return ctx.throw(500, e);
    }

    if(!book) {
        // 존재하지 않으면
        ctx.status = 404;
        ctx.body = { message: 'book not found' };
        return;
    }

    ctx.body = book;
};

results matching ""

    No results matching ""