KDT/TIL
8/31 TIL : File-system(JS, Promise, async/await), Routing w/o framework
ebulsok
2022. 9. 18. 18:21
๐ File-system
- node์ ๋ชจ๋์ด๊ธฐ ๋๋ฌธ์ CommonJS ๋ฐฉ์์ผ๋ก ๋ถ๋ฌ ์ฌ ์ ์์
- const fs = require('fs');
๐ฉ ํ์ผ์ ์ฝ์ ๋๋ readFile๋ฉ์๋๋ฅผ ์ฌ์ฉ
- ํ์ผ์ ์ฝ๋ ๊ฒ์ ์๊ฐ์ด ํ์ํ ์์ ์ด๊ธฐ ๋๋ฌธ์ ์ผ์ข ์ ์๋ฒ ํต์ ๊ณผ ๋น์ทํจ => ๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก callback์ ์ฌ์ฉ
- fs.readfile('ํ์ผ์์น', '์ ๋์ฝ๋ํฌ๋งท', callback(err, data) { });
- err๋ ํ์ผ ์ฝ๊ธฐ๋ฅผ ์คํจํ์ ๋ Error ์ฝ๋๋ฅผ ๋ฐํ
- data๋ ํ์ผ ์ฝ๊ธฐ๋ฅผ ์ฑ๊ณตํ์ ๋ ์ฝ์ data๋ฅผ ๋ฐํ
const fs = require('fs');
fs.readFile('./readme.txt', 'utf-8', (err, data) => {
if (err) console.log(err);
else console.log(data);
});
๐ฉ ํ์ผ์ ์ฝ์ ๋๋ writeFile ๋ฉ์๋๋ฅผ ์ฌ์ฉ
- fs.writeFile('ํ์ผ์์น', data, '์ ๋์ฝ๋ํฌ๋งท', callback(err) { } );
- data๊ฐ ์๊ณ , ์ฐ๊ธฐ๋ฅผ ์คํจํ์ ๋ Error ์ฝ๋๋ฅผ ๋ฐํ
- ํ์ผ์ ์ด๊ธฐํํ ํ ๋ฎ์ด์์ฐ๋ ๊ฐ๋
const fs = require('fs');
const str = 'ํ์ผ ์ฐ๊ธฐ๋ฅผ ์ฑ๊ณตํ๋ฉด ์ด ๋ฌธ๊ตฌ๊ฐ ํ์ผ์ ๋ค์ด๊ฐ๋๋ค.';
fs.writeFile('./readme.txt', str, 'utf-8', (err) => {
if (err) console.log(err);
else console.log('writeFile succeed');
});
callback์ ๊ฐ๋ ์ฑ ์ ์ข๊ธฐ ๋๋ฌธ์ promise๋ผ๋ ๊ฐ๋ ์ด ๋์๊ณ ๊ทธ ์ดํ syntatic sugar(async, await)
๐ฉ File-system๊ณผ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ
readFile ๋ฉ์๋๋ฅผ ๋์์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ์์ผ๋ณด๊ธฐ
fs.readFile('./readme.txt', 'utf-8', function (err, data) {
if (err) throw err;
console.log('1๋ฒ', data.toString());
});
fs.readFile('./readme.txt', 'utf-8', function (err, data) {
if (err) throw err;
console.log('2๋ฒ', data.toString());
});
fs.readFile('./readme.txt', 'utf-8', function (err, data) {
if (err) throw err;
console.log('3๋ฒ', data.toString());
});
fs.readFile('./readme.txt', 'utf-8', function (err, data) {
if (err) throw err;
console.log('4๋ฒ', data.toString());
});
- callback ๋ฐฉ์์ ์ฌ์ฉ ๋ฐ ์ฝ๋ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ธฐ ๋๋ฌธ์ fs๋ promise ๋ฐฉ์ ๊ธฐ๋ฅ์ ์ ๊ณต
- ๊ธฐ์กด์ ๋ฉ์๋ ๋ช ๋ค์ Sync๋ฅผ ๋ถ์ด๋ฉด promise ๋ฐฉ์์ ์ฌ์ฉํ์ฌ ๋๊ธฐ์ ์ผ๋ก ์๋
- ์๋ฒ ์์์ ์๋ํ ๋๋ ์ ์์ ์ผ๋ก ์๋ํ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋น๋ฒํจ
let data = fs.readFileSync('./readme.txt');
console.log('1๋ฒ', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('2๋ฒ', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('3๋ฒ', data.toString());
data = fs.readFileSync('./readme.txt');
console.log('4๋ฒ', data.toString());
- ๋ฐ๋ผ์ ์๋ฒ ์์์ fs๋ฅผ ์ธ ๋๋ Promise๋ฅผ ์จ์ผ ํจ
- Promise์ ์ผ๋ก ์๋ํ๋ fs.promises๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉ
- fs.promises๋ ์ค์ค๋ก ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ํ๋จํ์ฌ resolve, reject๋ฅผ ๋ฐํํจ
๐ฉ Promise
- ์ผ์ข ์ ํด๋์ค, ๋ฐ๋ผ์ new๋ก ์ฌ์ฉ
- const promise = new Promise(function(resolve, reject) { });
- resolve, reject๋ผ๋ 2๊ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ callback ํจ์๋ก ๋ฐ์์ ์ฌ์ฉ, ๋ฐ์ดํฐ๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ณด๋ผ ์ ์์
- promise๊ฐ ํ ๋น๋๋ฉด resolve/reject๊ฐ callback ๋ ๋๊น์ง ๋ฌดํ ๋๊ธฐ(pending ์ํ)
- resolve๋ then์ผ๋ก, reject๋ catch๋ก ๋ฐ์
const promise = new Promise((resolve, reject) => {
const name = 'bulsok';
if (name === 'bulsok') {
setTimeout(() => {
resolve('My name is bulsok');
}, 3000);
} else {
reject('My name is not bulsok');
}
});
promise
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
const fs = require('fs').promises;
fs.readFile('./readme.txt', 'utf-8')
.then((data) => {
console.log('1๋ฒ', data.toString());
return fs.readFile('./readme.txt', 'utf-8');
})
.then((data) => {
console.log('2๋ฒ', data.toString());
return fs.readFile('./readme.txt', 'utf-8');
})
.then((data) => {
console.log('3๋ฒ', data.toString());
return fs.readFile('./readme.txt', 'utf-8');
})
.then((data) => {
console.log('4๋ฒ', data.toString());
})
.catch((err) => {
throw err;
});
- function ์์ async๋ฅผ ๋ถ์ด๋ฉด ํญ์ Promise๋ฅผ ๋ฐํ, await ํค์๋ ์ฌ์ฉ ๊ฐ๋ฅ
- await๋ promise๊ฐ ๊ฒฐ๊ณผ(resolve, reject)๋ฅผ ๊ฐ์ ธ๋ค ์ค ๋๊น์ง ๊ธฐ๋ค๋ฆผ
- ํจ์๋ฅผ ์ ์ธ๋ง ํ๊ณ ์คํํ์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฃผ์ํ ๊ฒ
const fs = require('fs').promises;
async function main() {
let data = await fs.readFile('./readme.txt', 'utf-8');
console.log('1๋ฒ', data);
data = await fs.readFile('./readme.txt', 'utf-8');
console.log('2๋ฒ', data);
data = await fs.readFile('./readme.txt', 'utf-8');
console.log('3๋ฒ', data);
data = await fs.readFile('./readme.txt', 'utf-8');
console.log('4๋ฒ', data);
}
main();
๐ Routing: ๋คํธ์ํฌ ์์์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ๋ ์ต์ ์ ๊ฒฝ๋ก๋ฅผ ์ ํํ๋ ๊ณผ์
route.js
// @ts-check
const fs = require('fs').promises;
async function getPosts() {
const jsonPosts = await fs.readFile('database.json', 'utf-8');
return JSON.parse(jsonPosts).posts;
}
async function savePosts(posts) {
const content = {
posts,
};
return fs.writeFile('database.json', JSON.stringify(content), 'utf-8');
}
const routes = [
// ๋ธ๋ก๊ทธ ๋ชฉ๋ก์ ๊ฐ์ ธ์ค๋ API
{
url: '/posts',
id: 'undefined',
method: 'GET',
callback: async () => {
const posts = await getPosts();
return {
statusCode: 200,
body: {
posts,
totalCount: posts.length,
},
};
},
},
// ํน์ ID์ ๋ธ๋ก๊ทธ ๊ธ์ ๊ฐ์ ธ์ค๋ API
{
url: '/posts',
id: 'number',
method: 'GET',
callback: async (id) => {
const posts = await getPosts();
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',
id: 'undefined',
method: 'POST',
callback: async (id, newPost) => {
const posts = await getPosts();
posts.push({
id: posts[posts.length - 1].id + 1,
title: newPost.title,
content: newPost.content,
});
savePosts(posts);
return {
statusCode: 200,
body: '์๋ก์ด ๊ธ์ด ๋ฑ๋ก๋์์ต๋๋ค.',
};
},
},
// ํน์ ID์ ๊ธ์ ์์ ํ๋ API
{
url: '/posts',
id: 'number',
method: 'PUT',
callback: async (id, modiPost) => {
const posts = await getPosts();
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',
};
}
posts[id - 1].title = modiPost.title;
posts[id - 1].content = modiPost.content;
savePosts(posts);
return {
statusCode: 200,
body: '๊ธ์ด ์์ ๋์์ต๋๋ค.',
};
},
},
// ํน์ ID์ ๊ธ์ ์ญ์ ํ๋ API
{
url: '/posts',
id: 'number',
method: 'DELETE',
callback: async (id) => {
const posts = await getPosts();
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',
};
}
posts.splice(id - 1, 1);
savePosts(posts);
return {
statusCode: 200,
body: '๊ธ์ด ์ญ์ ๋์์ต๋๋ค.',
};
},
},
];
module.exports = {
routes,
};
main.js
// @ts-check
const http = require('http');
const { routes } = require('./route.js');
// ์๋ฒ ์ ์
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
const urlArr = req.url ? req.url.split('/') : [];
let id;
if (urlArr.length > 2) id = parseInt(urlArr[2], 10);
else id = undefined;
async function main() {
const route = routes.find(
(_route) =>
req.url &&
req.method &&
'/' + urlArr[1] === _route.url &&
// req.url.search(_route.url) !== -1 &&
_route.method === req.method &&
typeof id === _route.id
);
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.body);
res.statusCode = result.statusCode;
res.end(JSON.stringify(result.body));
}
}
main();
});
// ์๋ฒ ์คํ
const PORT = 4000;
server.listen(PORT, () => {
console.log(`ํด๋น ์๋ฒ๋ ${PORT}๋ฒ ํฌํธ์์ ์๋ ์ค์
๋๋ค.`); // ์๋ฒ ์ฝ์
});
database.json
{"posts":[{"content":"hello, back-end","id":1,"title":"first"},{"content":"hello, back-end","id":2,"title":"second"},{"content":"hello, back-end","id":3,"title":"third"}]}