안녕하세요
오늘은 framework 없이 서버 사용해서 CRUD를 구현해보았습니다.
아무래도 framework 없이 구현하면 너무 노가다?스럽기는 하지만 자바스크립트의 비동기 방식의 원리를 이해하는 데에는 이만한 게 없습니다.
저는 블로그의 글을 작성, 수정, 삭제, 등록
이렇게 수행할 수 있는 api를 코드로 작성했습니다. 참고하실 분들은 참고하시길 바랄게요
// @ts-check
/**
* @typedef Post
* @property {number} id
* @property {string} title
* @property {string} content
*/
/** @type {Post[]} */
const posts = [
{
id: 1,
title: '첫번째 블로그 글',
content: '첫번째 내용입니다.',
},
{
id: 2,
title: '두번째 블로그 글',
content: '두번째 내용입니다',
},
{
id: 3,
title: '세번째 블로그 글',
content: '세번째 내용',
},
];
const routes = [
// 블로그 목록을 가져오는 API
{
url: '/posts',
method: 'GET',
id: 'undefined',
callback: async () => ({
statusCode: 200,
body: {
posts: posts.map((post) => ({
id: post.id,
title: post.title,
})),
totalCount: posts.length,
},
}),
},
// 특정 ID의 블로그 글을 가져오는 API
{
url: '/posts',
method: 'GET',
id: 'number',
callback: async (postId) => {
const id = postId;
if (!id) {
return {
statusCode: 404,
body: 'Not found',
};
}
const result = posts.find((post) => post.id === id);
if (!result) {
return {
statusCode: 404,
body: 'ID Not found',
};
}
return {
statusCode: 200,
body: result,
};
},
},
// 새로운 글을 쓰는 API
{
url: '/posts',
method: 'POST',
id: 'undefined',
callback: async (id, newPost) => {
posts.push({
id: posts[posts.length - 1].id + 1,
title: newPost.title,
content: newPost.content,
});
return {
statusCode: 200,
body: 'post is uploaded',
};
},
},
// 수정하는 API
{
url: '/posts',
method: 'PUT',
id: 'number',
callback: async (id, newPost) => {
if (!id) {
return {
statusCode: 404,
body: 'Not found',
};
}
const result = posts.find((post) => post.id === id);
if (!result) {
return {
statusCode: 404,
body: 'Not found',
};
}
const modifyPost = newPost;
modifyPost.id = id;
posts[id - 1] = modifyPost;
return {
statusCode: 200,
body: modifyPost,
};
},
},
// 삭제하는 API
{
url: '/posts',
method: 'DELETE',
id: 'number',
callback: async (id) => {
if (!id) {
return {
statusCode: 404,
body: 'Not found',
};
}
const result = posts.find((post) => post.id === id);
if (!result) {
return {
statusCode: 404,
body: 'Not found',
};
}
posts.splice(id - 1, 1);
return {
statusCode: 200,
body: 'post deleted',
};
},
},
];
module.exports = {
routes,
};
// @ts-check
const http = require('http');
const { routes } = require('./route');
const server = http.createServer((req, res) => {
const urlArr = req.url ? req.url.split('/') : [];
let id;
console.log(urlArr);
if (urlArr.length > 2) {
id = parseInt(urlArr[2], 10);
} else {
id = undefined;
}
async function main() {
const route = routes.find(
(_route) =>
req.url &&
req.method &&
req.url.search(_route.url) !== -1 &&
_route.method === req.method &&
typeof id === _route.id
);
res.setHeader('Content-Type', 'application/json; utf-8');
if (!route) {
console.log('해당 API를 찾을 수 없습니다.');
res.statusCode = 404;
res.end('Not found');
} else {
let newPost;
if (req.method === 'POST' || req.method === 'PUT') {
newPost = await new Promise((resolve, reject) => {
req.setEncoding('utf-8');
req.on('data', (data) => {
if (data !== undefined) {
resolve(JSON.parse(data));
} else {
reject();
}
});
});
}
const result = await route.callback(id, newPost);
console.log(result);
res.statusCode = result.statusCode;
res.end(JSON.stringify(result.body));
}
}
main();
/**
* GET /posts 목록 가져오기
* GET /posts/:id 특정 글 내용 가져오기
* POST /posts 새로운 글 올리기
* PUT /posts/:id 특정 글 내용 수정하기
* DELETE /posts/:id 특정 글 삭제하기
*/
// if (req.url === '/posts' && req.method === 'GET') {
// const result = {
// posts: posts.map((post) => ({
// id: post.id,
// title: post.title,
// })),
// totalCount: posts.length,
// };
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// res.statusCode = 200;
// res.end(JSON.stringify(result));
// } else if (id !== -1 && req.method === 'GET') {
// const result = posts.find((post) => post.id === id);
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// if (result) {
// console.log('블로그의 특정 id를 가지는 글의 내용을 보여주는 api 입니다');
// res.statusCode = 200;
// res.end(JSON.stringify(result));
// } else {
// console.log('해당 id를 가지는 포스트를 찾을 수 없었습니다.');
// res.statusCode = 404;
// res.end('해당 id를 가지는 포스트를 찾을 수 없었습니다.');
// }
// } else if (req.url === '/posts' && req.method === 'POST') {
// req.setEncoding('utf-8');
// req.on('data', (data) => {
// const newPost = JSON.parse(data);
// posts.push({
// id: posts[posts.length - 1].id + 1,
// title: newPost.title,
// content: newPost.content,
// });
// });
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// res.statusCode = 200;
// res.end('새로운 글이 등록 되었습니다.');
// console.log('블로그의 새로운 글을 등록하는 api 입니다');
// } else if (id !== -1 && req.method === 'PUT') {
// req.setEncoding('utf-8');
// req.on('data', (data) => {
// const modifyPost = JSON.parse(data);
// modifyPost.id = id;
// posts[id - 1] = modifyPost;
// });
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// res.statusCode = 200;
// res.end(`수정 된 포스트의 id 번호는 ${id} 입니다.`);
// console.log('블로그의 특정 글을 수정하는 api 입니다');
// } else if (id !== -1 && req.method === 'DELETE') {
// posts.splice(id - 1, 1);
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// res.statusCode = 200;
// res.end(`id 번호가 ${id}인 포스트를 삭제 하였습니다.`);
// console.log('블로그의 특정 글을 삭제하는 api 입니다.');
// } else {
// res.setHeader('Content-Type', 'application/json; charset=utf-8');
// res.statusCode = 404;
// res.end('해당 api 는 존재하지 않습니다.');
// console.log('해당 api 는 존재하지 않습니다.');
// }
});
const PORT = 4000;
server.listen(PORT, () => {
console.log(`해당 서버는 ${PORT}번 포트에서 작동 중입니다.`);
});
server.js는 서버 실행을 위한 코드이고 route.js는 기능을 수행하는 코드입니다.
다음에는 framework를 이용하여 구현하는 것을 올려보도록 하겠습니다~
그럼 다들 bye~