세리프 따라잡기

nodejs app제작(전송 데이터 받기), 파일생성과 리다이렉션, 글 수정 및 삭제 버튼 구현 본문

Node.js

nodejs app제작(전송 데이터 받기), 파일생성과 리다이렉션, 글 수정 및 삭제 버튼 구현

맑은 고딕 2021. 1. 7. 23:35

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가지에 대한 기본을 다 배웠다! 🤗 짝짝짝~ 🙌

Comments