세리프 따라잡기
nodejs app제작(전송 데이터 받기), 파일생성과 리다이렉션, 글 수정 및 삭제 버튼 구현 본문
22. POST 방식으로 전송된 데이터 받기
stackoverflow.com/questions/4295782/how-to-process-post-data-in-node-js 검색을 통한 코드 참고.
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring'); //qs가 쿼리스트링이라는 nodejs 모듈을 가져오는 것. qs.parse 코드 줄에서 사용
function templateHTML(title, list, body) {
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<a href="/create">create</a>
${body}
</body>
</html>
`;
}
function templateList(filelist) {
var list = '<ul>';
var i = 0;
while (i < filelist.length) {
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list + '</ul>';
return list;
}
var app = http.createServer(function (request, response) { //서버에 전달된 callback 함수. request는 요청할 때 웹 브라우저가 보낸 정보들. response는 응답할 때 우리가 웹 브라우저한테 전송할 정보들.
var _url = request.url;
var querydata = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
if (pathname === '/') {
if (querydata.id === undefined) {
fs.readdir('./data', function (err, filelist) {
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
response.writeHead(200);
response.end(template);
})
} else {
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
response.writeHead(200);
response.end(template);
});
});
}
} else if (pathname === '/create') {
fs.readdir('./data', function (err, filelist) {
var title = 'WEB - create';
var list = templateList(filelist);
var template = templateHTML(title, list,
`<form action="http://localhost:3000/create_process" method="POST">
<p><input type="text" name="title" placeholder="title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>`);
response.writeHead(200);
response.end(template);
});
} else if(pathname === '/create_process'){ //POST 방식으로 전송된 데이터를 nodejs에서 받기 위한 코드
var body = '';
request.on('data', function(data){
body += data; //→ body = body + data라는 것. callback이 실행될 때 마다 데이터를 추가해줌.
}); //request는 위의 함수에서 온 것이고, 이 코드는: 웹 브라우저가 post 방식으로 데이터를 전송할 때 데이터가 엄청나게 많으면 컴퓨터에 무리가 간다. 그런 경우를 대비해 nodejs에선 request.on 방식을 제공한다.
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description; //var title, description을 통해 제목과 본문값을 알아낼 수 있다. (아직 읽히진 않음. 후에 읽히도록 코드 추가할 것.)
//console.log(post);를 통해 host 데이터 확인해보기 → 이때 출력 {title: ~, description: ~}이면 정상 출력. post.title을 통해 배열 형식 비슷한 게 타이틀값이 되어 출력됨.
}); //더이상 들어올 정보가 없으면 이 callback 함수로 호출하게 함.
response.writeHead(200);
response.end('success'); //제대로 요청을 받았으면 성공 뜨게끔. 정상 출력
} else {
response.writeHead(404);
response.end('not found');
};
});
app.listen(3000);
data와 end를 이벤트라고 하는데, 이걸 이용해서 웹 브라우저로부터 전송된 데이터, post 방식으로 전송된 것을 가지고 올 수 있고. 또 쿼리스트링이라는 모듈의 parse 함수를 이용해서 정보를 객체화 할 수 있게 된다.
23. 데이터 디렉토리 안에 파일 형태로 저장하는 방법 (22번의 코드와 이어짐)
- 파일 저장하는 방법
공식 사이트 nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback 를 참고.
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){ //파일을 저장하는 방법에 대한 코드
response.writeHead(200);
response.end('success');
}); //err은 에러가 있을 때 에러를 처리하는 방법. 정상 callback이 되면 성공이 뜨게끔.
});
- 파일을 생성하고 리다이렉션 해주는 방법
stackoverflow.com/questions/11355366/how-to-redirect-users-browser-url-to-a-different-page-in-nodejs 참고 (검색)
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {location: `/?id=${title}`}); //200은 성공, 302는 페이지를 다른 곳으로 리다이렉션 시키라는 뜻.
response.end(); //302를 쓴다면 end 부분에 특별한 메시지가 필요하지 않으므로 지워줌.
}); //제대로 data 파일에는 파일이 생성되고, 생성된 파일을 리다이렉션 해주면서 페이지를 옮겨주는 게 정상 작동됨을 확인할 수 있다.
});
24. 글 수정 링크 생성
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
function templateHTML(title, list, body, control) { // control 이라는 변수를 만들어준다.
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`; // <a href="/create">create</a> <a href="/update">update</a> 부분을 ${control} 부분으로 바꿔줌. 그리고 앞선 html 코드는 각각 홈 부분과 id 부분에 넣어준다.
}
function templateList(filelist) {
var list = '<ul>';
var i = 0;
while (i < filelist.length) {
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list + '</ul>';
return list;
}
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;
if (pathname === '/') {
if (querydata.id === undefined) {
fs.readdir('./data', function (err, filelist) {
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/create">create</a>`); // 홈 부분이라 create 부분까지만 넣어줌.
response.writeHead(200);
response.end(template);
})
} else {
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`); // id 값을 선택한 부분이라 update 까지 포함된 전체 코드를 넣어준다. + 주소에 update?id=(누른 데이터명)이 뜨게 하려면 ?id=${title}을 넣어준다.
response.writeHead(200);
response.end(template);
});
});
}
} else if (pathname === '/create') {
fs.readdir('./data', function (err, filelist) {
var title = 'WEB - create';
var list = templateList(filelist);
var template = templateHTML(title, list,
`<form action="http://localhost:3000/create_process" method="POST">
<p><input type="text" name="title" placeholder="title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>`, ''); // ''는 안 넣어도 되지만, 공백이라도 넣어주는 게 좋다고..
response.writeHead(200);
response.end(template);
});
} else if(pathname === '/create_process'){
var body = '';
request.on('data', function(data){
body += data;
});
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {location: `/?id=${title}`});
response.end();
});
});
} else {
response.writeHead(404);
response.end('not found');
};
});
app.listen(3000);
25. 글 수정할 정보 전송
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
function templateHTML(title, list, body, control) {
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
}
function templateList(filelist) {
var list = '<ul>';
var i = 0;
while (i < filelist.length) {
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list + '</ul>';
return list;
}
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;
if (pathname === '/') {
if (querydata.id === undefined) {
fs.readdir('./data', function (err, filelist) {
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/create">create</a>`);
response.writeHead(200);
response.end(template);
})
} else {
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);
response.writeHead(200);
response.end(template);
});
});
}
} else if (pathname === '/create') {
fs.readdir('./data', function (err, filelist) {
var title = 'WEB - create';
var list = templateList(filelist);
var template = templateHTML(title, list,
`<form action="create_process" method="POST">
<p><input type="text" name="title" placeholder="title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>`, ''); //http://localhost:3000/ < 이 부분은 융통성이 없는 방식이라, 빼줌. 도메인을 달았을 때 동작을 안 할 수 있음.
response.writeHead(200);
response.end(template);
});
} else if(pathname === '/create_process'){
var body = '';
request.on('data', function(data){
body += data;
});
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {location: `/?id=${title}`});
response.end();
});
});
} else if(pathname === '/update'){ //update를 클릭했을 때 보여지는 화면 만들려면 read 기능이 필요한데, 앞서 만든 id값이 있는 경우에 대한 처리 코드가 있기 때문에 복붙해서 온다.
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(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" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>`, `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);//앞선 form 정보 코드를 복붙함. 고칠 부분은 주소와 수정 기능을 사용하려면 필요한 기존 정보(value=${변수이름})를 읽어와야 함. html의 input tag = value 이다. 각각 제목 부분(value 포함)과 textarea 부분(value 없이 태그 안에만)에 넣어준다. + 추가로 제목이 바뀌게 하면 안되니까, input type을 히든으로 하는 코드를 한 줄 넣어줌.
response.writeHead(200);
response.end(template);
}); // 새로고침했을 때 주소가 update가 넣어진 기존 id값으로 변경되면 정상 출력이 된 것.
});
} else {
response.writeHead(404);
response.end('not found'); // update의 form 코드에서 hidden 줄이 정상 작동되는 지 보려면 제목을 바꾼 뒤 제출을 하여 검사를 해보면 id값은 그대로인데, 타이틀만 변경되는 것을 볼 수 있다. (아직 404가 뜸.)
};
});
app.listen(3000);
26. 파일명 변경, 내용 저장 (25번과 계속 이어짐)
nodejs.org/api/fs.html#fs_fs_rename_oldpath_newpath_callback 검색하여 참고. 문법: fs.rename(oldPath, newPath, callback)
else if(pathname === '/update_process'){ //create_process 부분과 비슷한 코드라 복붙해온다.
var body = '';
request.on('data', function(data){
body += data;
});
request.on('end', function(){
var post = qs.parse(body);
var id = post.id; //id 값도 받았기 때문에 코드를 추가해준다.
var title = post.title;
var description = post.description; //post 정보로 데이터가 잘 도착했는지 확인하기 위해 console.log(post);를 이용한다. [수시로 확인해주면 좋다] 그러면 id, title, description이 제대로 들어오는 걸 확인할 수 있다.
fs.rename(`data/${id}`, `data/${title}`, function(err){ //이 코드가 잘 실행되었으면 update의 title값 수정을 통해 내 data 파일의 해당 파일명이 바뀐것을 볼 수 있다. (ex. CSS → CSS3)
fs.writeFile(`data/${title}`, description, 'utf8', function(err){ //본문을 수정할 수 있게 하는 코드.
response.writeHead(302, {location: `/?id=${title}`});
response.end();
}); //실행이 완벽하다면 제목은 물론 본문까지 수정할 수 있고, 수정된 것이 저장된 데이터 파일까지 바꾸는 것을 확인할 수 있다. (ex. 필자 data 폴더 내의 CSS 파일의 제목과 본문이 수정됨.)
})
});
} //pathname === '/update' ~~ ; 다음 코드로 이 코드가 오면 된다.
27. 글 삭제와 버튼 구현
- 25번의 52번째줄 이하 코드를 수정한 것. [form 형식으로 delete 버튼 구현]
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${title}">
<input type="submit" value="delete">
</form>`); //<a href="/delete?id=${title}">delete</a> 이렇게 만들면 링크로 삭제 버튼을 만드는 건데, 이러면 아주아주 대참사가 일어나니 form 형식으로 만들고 방식은 post로 보내준다.
response.writeHead(200);
response.end(template);
});
- 코드 수정 및 추가 [글 삭제 하기]
nodejs.org/api/fs.html#fs_fs_unlink_path_callback 참고. 문법: fs.unlink(path, callback)
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}`, function(err){ //delete file에 대한 코드
response.writeHead(302, {location: `/`}); //삭제가 끝나면 사용자를 홈으로 보내는 코드
response.end(); //정상 출력이 된다면, delete 버튼을 누름과 동시에 웹 내에서는 물론이고 본인의 데이터 폴더의 파일 또한 지워지는 것을 볼 수 있다. (ex. mongo file remove)
})
});
} // update_process ~~ 에 해당하는 26번 코드들 밑에 이걸 넣으면 된다.
- 최종 완성 코드 [CRUD 끝]
var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
function templateHTML(title, list, body, control) {
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
}
function templateList(filelist) {
var list = '<ul>';
var i = 0;
while (i < filelist.length) {
list = list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i = i + 1;
}
list = list + '</ul>';
return list;
}
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;
if (pathname === '/') {
if (querydata.id === undefined) {
fs.readdir('./data', function (err, filelist) {
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`, `<a href="/create">create</a>`);
response.writeHead(200);
response.end(template);
})
} else {
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${title}">
<input type="submit" value="delete">
</form>`);
response.writeHead(200);
response.end(template);
});
});
}
} else if (pathname === '/create') {
fs.readdir('./data', function (err, filelist) {
var title = 'WEB - create';
var list = templateList(filelist);
var template = templateHTML(title, list,
`<form action="create_process" method="POST">
<p><input type="text" name="title" placeholder="title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>`, '');
response.writeHead(200);
response.end(template);
});
} else if(pathname === '/create_process'){
var body = '';
request.on('data', function(data){
body += data;
});
request.on('end', function(){
var post = qs.parse(body);
var title = post.title;
var description = post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {location: `/?id=${title}`});
response.end();
});
});
} else if(pathname === '/update'){
fs.readdir('./data', function (err, filelist) {
fs.readFile(`data/${querydata.id}`, 'utf8', function (err, description) {
var title = querydata.id;
var list = templateList(filelist);
var template = templateHTML(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" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>`, `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);
response.writeHead(200);
response.end(template);
});
});
} else if(pathname === '/update_process'){
var body = '';
request.on('data', function(data){
body += data;
});
request.on('end', function(){
var post = qs.parse(body);
var id = post.id;
var title = post.title;
var description = post.description;
fs.rename(`data/${id}`, `data/${title}`, function(err){
fs.writeFile(`data/${title}`, description, 'utf8', function(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}`, function(err){
response.writeHead(302, {location: `/`});
response.end();
})
});
} else {
response.writeHead(404);
response.end('not found');
};
});
app.listen(3000); // CRUD 부분 최종 완성!!
이로써 CRUD 라 일컫는 정보 기술의 핵심적 operation 4가지에 대한 기본을 다 배웠다! 🤗 짝짝짝~ 🙌
'Node.js' 카테고리의 다른 글
nodejs의 보안(입·출력)과 API에 대해, 끝으로…. (0) | 2021.01.11 |
---|---|
nodejs 객체와 모듈에 대해 (0) | 2021.01.10 |
nodejs에서 동기와 비동기, callback, 패키지 매니저(pm2), html form, 글쓰기 ui 생성 (0) | 2021.01.06 |
nodejs에서 파일 목록 알아내기, 글 목록 출력하기, 함수 문법 (0) | 2021.01.05 |
nodejs app제작(not found, 홈페이지 구현), 반복문, 배열(추가 및 제거) (0) | 2021.01.05 |