song.log

[Node.js] 글생성, 글수정, 글삭제 : post방식으로 전송된 데이터 받기, Redirection, 객체를 이용해서 템플릿 기능 정리 정돈하기 본문

DevLog/Node.js

[Node.js] 글생성, 글수정, 글삭제 : post방식으로 전송된 데이터 받기, Redirection, 객체를 이용해서 템플릿 기능 정리 정돈하기

SingaKorean 2019. 12. 21. 20:01
반응형

 

 

1. 글생성:  UI 만들기, Post방식으로 전송된 데이터 받기 

기존 pathname '/' 이외에 pathname '/create'을 생성해 글을 작성할 수 있는 페이지를 작성

아래의 코드를 추가 기존의 template에다가 html form을 추가

    else if(pathname === "/create"){
      fs.readdir('./data', function(error, 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);
     });
    }

 

form의 post 방식으로 가져온 데이터를 /create_process페이지로 넘어가면서 확인하고자 할 때, 

createServer의 인자인 request로 데이터를 요청하고, 받은 데이터를 querystring모듈의 parse로 객체화 하여 데이터를 console에 출력할 수 있다.

 

    else if(pathname === "/create_process"){
      var body = '';
      request.on('data', function(data){
        body += data;
      });
      // 정보 수신이 끝났을 경우
      request.on('end', function(){
        var post = qs.parse(body); //(가져온 데이터를 객체화 한 것)
        console.log(post);
        console.log(post.title);
        console.log(post.description);

      });
      response.writeHead(200);
      response.end('success');
    }

2. 파일 생성과 리다이렉션

 

fs.writeFile('파일경로', '저장내용', encoding, 콜백함수) 

 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: URL});

이 때 302는 일시적으로 페이지를 리다이렉션할 때 쓰이는 번호

 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();
          })
      });

 

3. 글 수정:  링크 생성/수정할 정보 전송/수정할 내용 저장

 

먼저 templateHTML의 형태 수정

: control을 추가해서 홈페이지에서는 create만 보이고 각 페이지에서는 update가 보이도록 수정

function templateHTML(title, list, body, control){
  return `
  <!doctype html>
  <html>
  <head>
    <title>WEB1 - ${title}</title>
    <meta charset="utf-8">
  </head>
  <body>
    <h1><a href="/">WEB2</a></h1>
    ${list}
    ${control}
    ${body}
  </body>
  </html>
  `;
}

 

모든 메뉴가 보이는 부분에 a태그로 링크 설정

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><p>${description}</p>`,
            `<a href="/create">create</a>  <a href="/update?id=${title}">update</a>`);

            response.writeHead(200);
            response.end(template);
          });
        });
      }

글 수정 부분에서는 기존의 내용을 가져올 수 있도록 fs.readFile()을 통해 데이터를 가져오고 이 데이터를 input의 value 또는 text로 표시되게끔 입력

  else if(pathname === '/update'){
      fs.readdir('./data', function(error, 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);
        });
      });
    }

수정된 데이터를 각 페이지의 파일에 저장할 때, 기존의 id값을 새로 입력 받은 title로 수정하기 위해 fs.rename()을 사용

fs.rename('이전 경로','새로운 경로','콜백함수') 그 안에 fs.writeFile('새로운 경로', '페이지 내용', 'encoding', '콜백함수')로 파일을 수정하고 저장할 수 있다. 

  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,'utf-8',function(err){
            response.writeHead(302,
            {Location: `/?id=${title}`});
            response.end();
          });
        });
      });
    }

 

4. 글삭제 : 삭제버튼 구현, 기능 완성

 

control 부분에 delete를 할 수 있는 버튼을 추가(링크는 따로 보여줄 페이지가 없기 때문에 X) 

form태그로 지울 id 값을 가지고 delete_process로 넘어감

 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><p>${description}</p>`,
            `<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);
          });
        });
      }

 

글 삭제 기능은 간단하다. post방식으로 받아온 id값으로 지우고자 하는 경로를 fs.unlink()에 넣고 그 다음으로 넘어갈 페이지를 정해주면 끝.

이 때 fs.unlink('경로','콜백함수')에 response.writeHead(302, '넘어갈 페이지')를 입력하면 된다. 

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();
        });
      });
    }

 

5. 객체를 이용해서 템플릿 기능 정리 정돈하기 : Refactoring

함수를 작성할 때, 성격이 같은 함수를 그룹핑하기 위해서는 함수의 접두사를 같은 것으로 하는 것이 좋다.  

그 후 같은 성격의 함수를 그룹핑하는 작업을 실행

 

var template = {
  HTML:function(title, list, body, control){
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      <h1><a href="/">WEB2</a></h1>
      ${list}
      ${control}
      ${body}
    </body>
    </html>
    `;
  },
  list: function(filelist){
    var list = '<ul>';
    var i = 0;
    while(i < filelist.length){
        list = list + `<a href='/?id=${filelist[i]}'><li>${filelist[i]}</li></a>`;
        i = i+1;
    }
    list = list + "</ul>";
    return list;
  }
}

 

그룹핑한 함수를 사용할 때는 아래와 같이 표시

 

  var list = template.list(filelist);
          var html = template.HTML(title, list,
            `<h2>${title}</h2><p>${description}</p>`,
          `<a href="/create">create</a>`,'');

 

<전체코드>

var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');



var template = {
  HTML:function(title, list, body, control){
    return `
    <!doctype html>
    <html>
    <head>
      <title>WEB1 - ${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      <h1><a href="/">WEB2</a></h1>
      ${list}
      ${control}
      ${body}
    </body>
    </html>
    `;
  },
  list: function(filelist){
    var list = '<ul>';
    var i = 0;
    while(i < filelist.length){
        list = list + `<a href='/?id=${filelist[i]}'><li>${filelist[i]}</li></a>`;
        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 = template.list(filelist);
          var html = template.HTML(title, list,
            `<h2>${title}</h2><p>${description}</p>`,
          `<a href="/create">create</a>`,'');
          response.writeHead(200);
          response.end(html);
        });


      } else {
        fs.readdir('./data', function(err, filelist){

          fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
            var title = queryData.id;
            var list = template.list(filelist);
            var html = template.HTML(title, list,
              `<h2>${title}</h2><p>${description}</p>`,
            `<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(html);
          });
        });
      }
    }
    else if(pathname === "/create"){
      fs.readdir('./data', function(error, filelist){
       var title = 'WEB - create';
       var list = template.list(filelist);
       var html = template.HTML(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(html);
     });
    }
    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,'utf-8',function(err){
          response.writeHead(302,
          {Location: `/?id=${title}`});
          response.end();
        });
      });
    }
    else if(pathname === '/update'){
      fs.readdir('./data', function(error, filelist){
        fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
          var title = queryData.id;
          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" 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(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 id = post.id;
        var title = post.title;
        var description = post.description;
        fs.rename(`data/${id}`,`data/${title}`,function(err){
          fs.writeFile(`data/${title}`,description,'utf-8',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);

 

 

참조한 생활코딩 URL :

https://opentutorials.org/module/3549/21135

https://opentutorials.org/module/3549/21136

https://opentutorials.org/module/3549/21137

https://opentutorials.org/module/3549/21138

https://opentutorials.org/module/3549/21139

https://opentutorials.org/module/3549/21140

https://opentutorials.org/module/3549/21141

https://opentutorials.org/module/3549/21142

https://opentutorials.org/module/3549/21147

반응형
Comments