๐ ํ๋ก์ ํธ ์ ๋ฆฌ
- ๋ฐ์ดํฐ ์คํค๋ง๊ฐ ๊ณ ์ ์ ์ด๋ฉฐ ํ์ฅ์ฑ์ด ์๋ ๊ธฐ์กด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ mongoDB๊ฐ ๋์ค๊ฒ ๋๋ค.
- ๋ฌธ์ ์งํฅ์ NoSQL๋ฐ์ดํฐ ๋ฒ ์ด์ค์ด๋ฉฐ Node.js ํ๊ฒฝ์์๋ mongoDB ๊ธฐ๋ฐ ODM(Object Data Modeling) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ mongoose์ ํจ๊ป ์ฌ์ฉํ๋ค.
- Node.js์์ import/export๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ณ ์ถ์ ๋๋ esm ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
- monogoose์์ ์คํค๋ง์ ๋ชจ๋ธ์ด๋ผ๋ ๊ฐ๋
์ด ์๋๋ฐ ์คํค๋ง๋ ์ปฌ๋ ์
์ ๋ค์ด๊ฐ๋ ๋ฌธ์ ๋ด๋ถ์ ๊ฐ ํ๋๊ฐ ์ด๋ค ํ์์ผ๋ก ๋์ด ์์ด ์๋์ง ์ ์ ํ๋ ๊ฐ์ฒด์ด๋ฉฐ ๋ชจ๋ธ์ ์ธ์คํด์ค๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ค์ ๋ก ์์
ํ๊ณ ์ฒ๋ฆฌํ ์ ์๋ ํจ์๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ด๋ค
- monogoDB compass๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฝ๊ฒ ์กฐํ/์์ ๊ฐ๋ฅํ๊ฒ ํ๋ GUI ํ๋ก๊ทธ๋จ์ด๋ค.
- Joi ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ์ฒด์ ๊ฐ ๊ฐ์ ๊ฒ์ฆ์ ์ฝ๊ฒ ํ ์ ์๊ฒ ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
- lean()ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ฒ์๋ถํฐ ๋ฐ์ดํฐ๋ฅผ JSON ํํ๋ก ์กฐํํ ์ ์๋ค.
- REST API์ mongoDB๋ฅผ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ๊ณผ ํ์ด์ง๋ค์ด์
๊ธฐ๋ฅ๊น์ง ๊ตฌํํด๋ณผ ์ ์์๋ค.
๐ฅ ์ฝ๋
import Router from 'koa-router';
import * as postsCtrl from './posts.ctrl';
const posts = new Router();
posts.get('/', postsCtrl.list);
posts.post('/', postsCtrl.write);
const post = new Router();
post.get('/', postsCtrl.read);
post.delete('/', postsCtrl.remove);
post.patch('/', postsCtrl.update);
posts.use('/:id', postsCtrl.checkObjectId, post.routes());
export default posts;
import Post from "../../models/post"
import mongoose from "mongoose";
import Joi from "joi"
const { ObjectId } = mongoose.Types;
export const checkObjectId = (ctx, next) => {
const { id } = ctx.params;
if (!ObjectId.isValid(id)) {
ctx.status = 400;
return;
}
return next();
}
export const write = async ctx => {
const schema = Joi.object().keys({
title: Joi.string().required(),
body: Joi.string().required(),
tags: Joi.array().items(Joi.string()).required()
})
const result = schema.validate(ctx.request.body);
if (result.error) {
ctx.status = 400;
ctx.body = result.error;
return;
}
const { title, body, tags } = ctx.request.body;
const post = new Post({ title, body, tags });
try {
await post.save();
ctx.body = post;
} catch (e) {
ctx.throw(500, e)
}
};
export const list = async ctx => {
const page = parseInt(ctx.query.page || "1", 10);
if (page < 1) {
ctx.status = 400;
return;
}
try {
const posts = await Post.find()
.sort({ _id: -1 })
.limit(10)
.skip((page - 1) * 10)
.lean()
.exec();
const postCount = await Post.countDocuments().exec();
ctx.set('Last-Page', Math.ceil(postCount / 10));
ctx.body = posts.map(post => ({
...post, body: post.body.length < 200 ? post.body : `${post.body.slice(0, 200)}...`
}))
} catch (e) {
ctx.throw(500, e)
}
};
export const read = async ctx => {
const { id } = ctx.params;
try {
const post = await Post.findById(id).exec();
console.log(id)
if (!post) {
ctx.status = 404;
return;
}
ctx.body = post
} catch (e) {
ctx.throw(500, e)
}
};
export const remove = async ctx => {
const { id } = ctx.params;
try {
await Post.findByIdAndRemove(id).exec();
ctx.status = 204;
} catch (e) {
ctx.throw(500, e)
}
};
export const update = async ctx => {
const { id } = ctx.params;
const schema = Joi.object().keys({
title: Joi.string(),
body: Joi.string(),
tags: Joi.array().items(Joi.string())
})
const result = schema.validate(ctx.request.body);
if (result.error) {
ctx.status = 400;
ctx.body = result.error;
return;
}
try {
const post = await Post.findByIdAndUpdate(id, ctx.request.body, {
new: true
}).exec();
if (!post) {
ctx.status = 404;
return;
}
ctx.body = post
} catch (e) {
ctx.throw(500, e)
}
};