우연히 들어가게 된 대학 연구실에서 웹 서버를 구현하는 과제를 받게 되었는데, 이를 Node.js로 구현을 하게 되었다.
여기에 추가적인 사항은 restful 한 구현이면 좋겠다는 것이였고, xml또는 json 형식을 데이터 형태로 교환하면 좋을 것 같다는 얘기를 해주었다.
그래서 이것들을 만족시킬 수 있도록 구현을 해보았다.
1차 코드
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | var http = require('http'); var fs = require('fs'); var url = require('url'); var template = require('./lib/template.js'); //나의 목표 : https://poiemaweb.com/js-rest-api var app = http.createServer(function(request,response){ var _url = request.url; //동적인 접근을 하도록 설정해준다. var queryData = url.parse(_url, true).query; var pathname = url.parse(_url, true).pathname; //가독성을 높이기 위해서 title로 묶어주었다. var title = queryData.id; var qs = require('querystring'); console.log(queryData.id); console.log(url.parse(_url, true)); var description = 'Hello, Node.js'; var contents = fs.readFileSync("./data/data.json"); var jsonContent = JSON.parse(contents); console.log(jsonContent.person[0].owner); console.log(jsonContent.person[0]); console.log(Object.keys(jsonContent.person).length); //처음 메인화면 if(pathname === '/') { if(title == undefined){ title = 'Welcome'; // var list = template.JSONList(jsonContent.person); var list = '<ol>'; for(var i=0;i<Object.keys(jsonContent.person).length;i++){ // var string = JSON.stringify(jsonContent.person[i]); console.log(jsonContent.person[i].owner); list = list + `<li><a href="/?id=${i+1}">${jsonContent.person[i].owner}</a></li>`; } list = list + '</ol>'; var html = template.HTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/post">post</a>`); response.writeHead(200); response.end(html); // //data폴더의 항목을 읽어 목록으로 만든다.(default) // fs.readdir('./data',(err, fileList)=>{ // //함수를 활용해 코드의 반복을 줄인다. // var list = template.list(fileList); // var html = template.HTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/post">post</a>`); // response.writeHead(200); // response.end(html); // }); } else{ title = jsonContent.person[title-1].owner var list = '<ol>'; for(var i=0;i<Object.keys(jsonContent.person).length;i++){ // var string = JSON.stringify(jsonContent.person[i]); console.log(jsonContent.person[i].owner); list = list + `<li><a href="/?id=${i+1}">${jsonContent.person[i].owner}</a></li>`; } list = list + '</ol>'; var description = ` phoneNumber : ${jsonContent.person[1].phoneNumber} owner : ${jsonContent.person[1].owner} corporation : ${jsonContent.person[1].corporation} ` var html = template.HTML(title, list, `<h2>${title}</h2>${description}`,`<a href="/post">post</a> <a href="/update?id=${title}">update</a> <form action="/delete_process" method="post"> <input type="hidden" name="id" value=${title}> <input type="submit"> </form> `); response.writeHead(200); response.end(html); // title = jsonContent.person[title-1].owner // var list = '<ol>'; // for(var i=0;i<Object.keys(jsonContent.person).length;i++){ // // var string = JSON.stringify(jsonContent.person[i]); // console.log(jsonContent.person[i].owner); // list = list + `<li><a href="/?id=${i+1}">${jsonContent.person[i].owner}</a></li>`; // } // list = list + '</ol>'; // // var description = ` // phoneNumber : ${jsonContent.person[1].phoneNumber} // owner : ${jsonContent.person[1].owner} // corporation : ${jsonContent.person[1].corporation} // ` // // var html = template.HTML(title, list, `<h2>${title}</h2>${description}`,`<a href="/post">post</a> // <a href="/update?id=${title}">update</a> // <form action="/delete_process" method="post"> // <input type="hidden" name="id" value=${title}> // <input type="submit"> // </form> // `); // response.writeHead(200); // response.end(html); //default; // fs.readFile(`data/${title}`, 'utf8', (err, description) => { // //if(err) throw err; // //템플릿을 활용해 문서를 처리하였다. // fs.readdir('./data',(err, fileList)=>{ // var list = template.list(fileList); // var html = template.HTML(title, list, `<h2>${title}</h2>${description}`,`<a href="/post">post</a> // <a href="/update?id=${title}">update</a> // <form action="/delete_process" method="post"> // <input type="hidden" name="id" value=${title}> // <input type="submit"> // </form> // `); // response.writeHead(200); // response.end(html); // }); // }) } } else if(pathname === '/get'){ } //post방식 구현 else if(pathname === '/post'){ var title = 'WEB - post'; fs.readdir('./data',(err, fileList)=>{ //함수를 활용해 코드의 반복을 줄인다. var list = template.list(fileList); var html = template.HTML(title, list, ` <form action="/post_process" method="post"> <p><input type="text" name="title" placeholder ="title"></p> <p> <textarea name="description" rows="8" cols="80" placeholder="description"></textarea> </p> <p> <input type="submit"> </p> </form> `,' '); response.writeHead(200); response.end(html); }); } else if(pathname === '/post_process'){ var body = ''; request.on('data', function(data){ body += data; }); //데이터량이 너무 많으면 통신 차단(보안) // if(body.length > 1e6){ // request.connection.destroy(); // } request.on('end', function(){ var post = qs.parse(body); var title = post.title; var description = post.description; console.log(post); console.log(post.title); console.log(post.description); fs.writeFile(`./data/${title}`, description, 'utf8', (err) => { response.writeHead(302, {Location: `/?id=${title}`}); response.end(); }); }); } //update를 구현하자. else if(pathname === '/update'){ fs.readFile(`data/${title}`, 'utf8', (err, description) => { //if(err) throw err; //템플릿을 활용해 문서를 처리하였다. fs.readdir('./data',(err, fileList)=>{ var list = template.list(fileList); var html = template.HTML(title, list, `<form action="/update_process" method="post"> <input type="hidden" name="id" value="${title}"> <p><input type="text" name="title" placeholder ="title" value="${title}"></p> <p> <textarea name="description" rows="8" cols="80" placeholder="description">${description}</textarea> </p> <p> <input type="submit"> </p> </form>`, ' '); response.writeHead(200); response.end(html); }); }) } else if(pathname === '/update_process'){ var body = ''; request.on('data', function(data){ body += data; }); request.on('end', function(){ var post = qs.parse(body); var title = post.title; var id = post.id; var description = post.description; console.log(post); console.log(post.title); console.log(post.id); console.log(post.description); fs.rename(`./data/${id}`, `./data/${title}`, (err) => { fs.writeFile(`./data/${title}`, description, 'utf8', (err) => { response.writeHead(302, {Location: `/?id=${title}`}); response.end(); }); }); }); } else if(pathname === '/delete_process'){ var body = ''; request.on('data', function(data){ body += data; }); request.on('end', function(){ var post = qs.parse(body); var id = post.id; fs.unlink(`./data/${id}`, (err) => { response.writeHead(302, {Location: `/`}); response.end(); }); }); } else { response.writeHead(404); response.end('Not found'); } }); app.listen(3000); | cs |
처음의 코드는 다른 패키지를 사용하지 않고, 서버를 만들고, _url에서 가져온 url을 활용하여 처리를 하는 형태로 만들었었다.
하지만, 공부를 하다보니, express라는 패키지를 활용하여 더 직관적으로 해결하는 방법이 있어서 그것을 활용해 두번째 코드를 기획하였다.
2차 코드
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var main = require('./router/main') ; var fs = require('fs'); // var contents = fs.readFileSync("./data/data.json"); // var jsonContent = JSON.parse(contents); var url = require('url'); // console.log(jsonContent.person[0].owner); // console.log(jsonContent.person[0]); // console.log(Object.keys(jsonContent.person).length); app.listen(3000, function(){ console.log("start, express server on port 3000"); }); //get방식의 요청을 처리한다. //data폴더 내의 정적인 파일들을 불러올 수 있도록 설정 app.use(express.static('data')); //json형태의 입력을 받는다. app.use(bodyParser.json()) //타입이 정해지지 않은 입력을 받는다. app.use(bodyParser.urlencoded({extended:true})) app.set('view engine', 'ejs'); //url routing app.use('/main', main); app.get('/', function(req,res){ // var _url = req.url; // var queryData = url.parse(_url, true).query; // var pathname = url.parse(_url, true).pathname; // console.log(_url); // console.log(queryData.get); // console.log(pathname); res.sendFile( __dirname + '/data/form.html'); }); //전체 데이터 출력 app.get('/get', function(req,res){ // console.log(queryData); res.sendFile( __dirname + '/data/data.json'); }); //원하는 데이터 출력 app.get('/get/:id', function (req, res, next) { console.log(req.params.id); var contents = fs.readFileSync("./data/data.json"); var jsonContent = JSON.parse(contents); console.log(jsonContent); res.json(jsonContent.person[req.params.id]); }); app.post('/user_post', function(req,res){ //get : req.param('email') console.log(req.body); // fs.writeFile(`./data/data.json`, description, 'utf8', (err) => { // response.writeHead(302, {Location: `/?id=${title}`}); // response.end(); // }); // res.send("welcome! " + req.body.email); //출력을 할때 값을 조정해야 할 필요가 있을때, 이런식으로 전송한다. //뷰 엔진 활용 res.render('email.ejs', {'phoneNumber' : req.body.phoneNumber}); }); app.post('/ajax_send_user', function(req, res){ console.log(req.body); var responseData = { 'phoneNumber' : req.body.phoneNumber, 'owner' : req.body.owner, 'corporation' : req.body.corporation }; var contents = fs.readFileSync("./data/data.json"); var jsonContent = JSON.parse(contents); //데이터 추가 jsonContent.person.push(responseData); console.log(jsonContent); var input = JSON.stringify(jsonContent); fs.writeFile(`./data/data.json`, input, 'utf8', function(error) { if(error) { console.log('[write auth]: ' + err); } else { console.log('[write auth]: success'); } }); //수정 필요 res.json(responseData); }); app.post('/delete', function(req,res){ //get : req.param('email') console.log(req.body); var contents = fs.readFileSync("./data/data.json"); var jsonContent = JSON.parse(contents); console.log(jsonContent); //splice(a,b)는 a부터 b개의 원소를 삭제한다. jsonContent.person.splice(req.body.id, 1); console.log(jsonContent); var input = JSON.stringify(jsonContent); fs.writeFile(`./data/data.json`, input, 'utf8', function(error) { if(error) { console.log('[write auth]: ' + err); } else { console.log('[write auth]: success'); } }); //뷰 엔진 활용 res.render('delete.ejs', {'id' : req.body.id}); }); //delete요청 처리 app.delete('/delete/:id', function (req, res, next) { console.log(req.params.id); var contents = fs.readFileSync("./data/data.json"); var jsonContent = JSON.parse(contents); console.log(jsonContent); //splice(a,b)는 a부터 b개의 원소를 삭제한다. jsonContent.person.splice(req.params.id, 1); console.log(jsonContent); var input = JSON.stringify(jsonContent); fs.writeFile(`./data/data.json`, input, 'utf8', function(error) { if(error) { console.log('[write auth]: ' + err); } else { console.log('[write auth]: success'); } }); res.sendFile( __dirname + '/data/form.html'); }); //delete관련 등등은 https://velopert.com/332 참고해서 //app.get('/get/:id', function(req, res) 이렇게 id값을 가져오면 될 것 같은데... //생각해보니까, 파라미터값으로 주어지면 되나? const http = require('http'); const https = require('https'); | cs |
2차 코드는 위와 같이 된다.
이 메인 코드 뒤에 data파일과 ejs 파일들이 추가적으로 있지만, 크게 중요하다 생각되지는 않아서 위의 코드만 쓴다.
우선 이 코드는 express를 활용하여 웹 서버를 구현하였다.
뭐 주석에 이런 저런 글을 써서 대충 이해 될 듯 싶지만, rest한 웹 페이지를 만들기 위해서 get요청과 post요청에 대해서 응답해주는 방식을 다르게 구현하였다.
웹 루트에서 접속하여 간단하게 하는 처리와, 임의의 url에서 get, post, delete등을 요청하면 그에 맞춰 응답을 할 수 있게끔도 설계하였다.
개인적으로 일반적인 사용자들이 접근하는 페이지와 개발자가 사용 할 수 있는 페이지를 나누어서 구현하기 위해서 이렇게 만들어 보았는데, 제대로 만든 것인지 약간 아쉬운 부분이 있긴 하다.
+) 이 코드 활용법
1. git을 가지고 있다면, git clone https://github.com/kyun1016/nodejs2.git 를 요청한다.
2. cd nodejs/restful_web/node
3. npm install
4. nodemon app(이부분은 자신이 사용하는 node.js 툴을 활용하면 된다.) (없다면, install npm nodemon -g)
(다른 툴로 pm2도 상당히 유용하게 사용하였다.)
미숙하지만 작업한 코드들은 아래에 들어있다.
'---------개인공부-------- > |Node.js|' 카테고리의 다른 글
[node.js] 학교 공지사항 크롤링(axios, cheerio, firebase-admin) (2) | 2020.01.01 |
---|