본문 바로가기

Web Development/Back-end

[생활코딩-Nodejs-17] '사용자 게시판 - 수정기능' 만들기

저번시간에는 사용자가 글을 입력하고, 저장하는 것 즉, '생성'과 '읽기' 까지 해보았습니다.

 

그럼 다음은 그 글을 수정할 수 있어야겠죠?

 

이제 수정기능을 추가해보도록 하겠습니다.

 

 

1. User Interface 만들기

 

우선 UI를 만들어야 하기 때문에 templateHTML부분을 수정해주겠습니다.

편의상의 이유로 control이라는 매개변수를 하나 추가해 그곳에 본래의 코드를 담아주었습니다.

이렇게 하구요.

이 페이지의 홈페이지에서는 굳이 수정버튼이 필요없겠쬬?

글 페이지에서만 수정버튼이 필요하기에 아래로 내려가서..

Query.ID값이 있을때 작동하는 곳에가서 작업해보겠습니다.

 

여기서 이렇게요.

Create버튼을 생성하는것과 똑같이 생성했으나,

사용자가 페이지를 수정할 때,

어떤페이지를 수정하는지 지정해줘야하잖아요?

그래서, querystring값으로, 현재 보고있는 페이지를 수정하도록 지정해주었습니다.

 

 

이제 수정하는 정보를 전송하는 부분을 처리해보겠습니다.

 

2. 정보의 전송

 

 

이렇게 Pathname이 Update일때 작동할 부분을 조건문을 추가해 만들어 주었습니다.

그리고, 위에서 pathname이 있을때 작동하는 부분과 똑같이 복사해왔습니다.

그리고 아래에 template부분을 고쳐줬는데요.

하나씩 살펴보겠습니다.

 

우선 form 작동 주소를 update_process로 해서 해당 값으로 데이터를 보낸다고 해두었구요.

우선 여기 표시한 부분부터 살펴보면,

수정 이전의 데이터를 텍스트창에 그대로 출력이 되도록 만들어 주었습니다.

여기서 알아두어야 할 것은

<input>태그에서는 value라는값을 통해 텍스트창에 값의 기본값을 줄 수 있다는 점,

<textarea>부분에서는 태그사이에 그냥 값을 주면 그것이 기본값이 된다는 점을 알아두면 좋을것 같습니다.

 

사용자가 만약, CSS파일의 제목을 CSS3으로 바꾼다고 가정합시다.

그럴 경우 CSS3파일을 읽으려고할텐데, 해당파일을 없단 말이에요?

그럼 기존의 제목과 대조할 부분이 필요합니다.

그래서 두 값을 모두 가져오게 하기위해 해당 부분이 추가되었습니다.

그런데, 사용자는 이를 볼 필요가 없으니 hidden으로 처리해주었구요.

 

자, 그럼 데이터가 어떻게 나오나 한번 살펴볼까요?

 CSS파일의 제목 부분만을 CSS3으로 바꾸어주었습니다.

그랬더니 F12를 검사창에 네트워크 탭에서 확인해보면,

다음과같이

id는 기존의 제목값인, CSS

그리고 title은 사용자가 수정한 값인, CSS3

로 출력되는 것을 확인할 수 있습니다.

 

이제 이걸 통해 완성시켜보겠습니다.

 

3. 웹페이지의 완성

이렇게, 해주면되는데요.

우선, 수정기능 정보의 전달을 update_process로 했기에, 해당 부분을 받아주는 else조건문을 만들어주었습니다.

 

그리고 나머지 빨간부분은 위에서,

글쓰기 기능을 실행했을 때, 데이터를 받아서 처리해주는 부분의 코드를 그대로 가져왔구요.

노란부분만을 수정해주었습니다.

 

id값을 받았기에 id변수를 만들어주었구요.

fs.rename이라는 Nodejs의 기능을 사용해서, 사용자가 제목을 바꾸었을 때,

제목이 바뀌게 동작하도록 처리해주었습니다.

 

양식은 다음과 같습니다.

그리고 description 정보부분을 처리했던 부분은,

글쓰기에서 사용했던 부분과 동일하게 가져와서 사용했습니다.

 

 

완성된 코드는 다음과 같습니다.

 

 

var http = require('http'); // http 모듈
var fs = require('fs'); // filesystem 모듈
var url = require('url'); // URL 모듈
var qs = require('querystring'); //querystring 모듈

//template 내용 HTML 뼈대를 함수로 만들기.
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+=1;
  }
  list = list +'</ul>';
  return list;
}

var app = http.createServer(function(request,response){
    var _url = request.url; //URL 요청
    var queryData = url.parse(_url, true).query; //URL을 분석하는 모듈 중, querystring 값
    var pathname = url.parse(_url, true).pathname; // URL을 분석하는 모듈 중, pathname 값
    //요청한 pathname이 루트값이라면 , if문이 실행
    if(pathname === '/'){ //Pathname이 루트 값일 경우 실행되는 코드
      if(queryData.id === undefined){
          //디렉토리를 읽는 함수 filelist변수가 파일목록. 배열로 반환.
          fs.readdir('./data', function(err, filelist){
            var title = 'Welcome';
            var description = 'Hello, Node.js';
            var list = templateList(filelist); //파일목록배열을 list변수에 할당.
            //HTML 뼈대 함수를 호출해 template 변수에 할당.
            var template = templateHTML(title, list, 
              `<h2>${title}</h2>${description}`,
              `<a href="/create">Create</a>`
              );
            response.writeHead(200); // 페이지가 정상적으로 출력되면 200, 오류페이지면 404.
            response.end(template); //화면출력하는부분에 template변수를 넣어줘서 출력.
          });

      //요청한 pathname이 루트값이 아니라면,대신 queryData.id가 있다면, else문 실행.
      } else {
        //디렉토리를 읽는 함수 filelist변수가 파일목록. 배열로 반환.
        fs.readdir('./data', function(err, filelist){
        //파일을 읽는 함수. description변수가 파일.
          fs.readFile(`data/${queryData.id}`, 'utf-8', 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); // 페이지가 정상적으로 출력되면 200, 오류페이지면 404.
            response.end(template); //화면출력하는부분
          });
        });
      };

    //pathName이 Create라면 실행할 조건문. 생성기능을 할 때 실행될 조건문. 데이터를 보내자!
    } else if(pathname ==='/create'){
          //디렉토리를 읽는 함수 filelist변수가 파일목록. 배열로 반환.
          fs.readdir('./data', function(err, filelist){
            var title = 'WEB - Create';
            var list = templateList(filelist); //파일목록배열을 list변수에 할당.
            //HTML 뼈대 함수를 호출해 template 변수에 할당.
            var template = templateHTML(title, list, `
            <!--form 태그-->
            <form action="http://localhost:3000/create_process" method="POST">
              <p><input type="text" name="title" placeholder="제목입력"></p>
              <p><textarea name="description" placeholder="본문입력"></textarea></p>
              <p><input type="submit"></p>
            </form> 
            `, '');
            response.writeHead(200); // 페이지가 정상적으로 출력되면 200, 오류페이지면 404.
            response.end(template); //화면출력하는부분에 template변수를 넣어줘서 출력.
          });

    //글쓰기를 실행했을 때 데이터를 받아온 데이터를 처리하는 조건문.
    } else if(pathname === '/create_process'){
      var body=''; // body에 빈 변수 선언.
      request.on('data', function(data){ //콜백함수. 서버에서 수신한 정보를 data 매개변수에 담음.
        body = body + data; //데이터가 전송될 때마다, 빈 변수 body에다가 전송된 데이터를 추가해줌.
      });
      request.on('end', function(){ // 데이터를 호출하다가, 데이터를 다 받은 뒤 할 실행될 함수.
        var post = qs.parse(body); //포스트에 바디에 저장된, 데이터를 querystring body부분을 통해 전달받음.
        var title = post.title;
        var description = post.description;
        fs.writeFile(`data/${title}`, description, 'utf8', function(error){
          //200 성공,  404 실패, 302 리다이렉션
          response.writeHead(302, {Location: `/?id=${title}`}); 
          response.end(); //화면출력하는부분
        })
      });
    
    
    //pathname이 update일 때, 즉 '수정'기능을 수행하는 조건문을 추가.
    }else if(pathname === '/update'){
      //디렉토리를 읽는 함수 filelist변수가 파일목록. 배열로 반환.
      fs.readdir('./data', function(err, filelist){
      //파일을 읽는 함수. description변수가 파일.
      fs.readFile(`data/${queryData.id}`, 'utf-8', function(err, description){
        var title = queryData.id
        var list = templateList(filelist);
        var template = templateHTML(title, list, 
        `
        <!--form 태그-->
        <form action="http://localhost:3000/update_process" method="POST">
          <input type="hidden" name="id" value="${title}">
          <p><input type="text" name="title" placeholder="수정할 제목" value=${title}></p>
          <p><textarea name="description" placeholder="수정할 본문입력">${description}</textarea></p>
          <p><input type="submit"></p>
        </form> 
        `,
        `<a href="/create">Create</a> 
        <a href="/update?id=${title}">Update</a>`
        );
        response.writeHead(200); // 페이지가 정상적으로 출력되면 200, 오류페이지면 404.
        response.end(template); //화면출력하는부분
        });
      });
    //위에서 '수정'기능을 사용해 보낸 데이터를 받는 부분. pathname 이 update_process일 때 조건문.
    }else if(pathname == '/update_process'){
      var body=''; // body에 빈 변수 선언.
      request.on('data', function(data){ //콜백함수. 서버에서 수신한 정보를 data 매개변수에 담음.
        body = body + data; //데이터가 전송될 때마다, 빈 변수 body에다가 전송된 데이터를 추가해줌.
      });
      request.on('end', function(){ // 데이터를 호출하다가, 데이터를 다 받은 뒤 할 실행될 함수.
        var post = qs.parse(body); //포스트에 바디에 저장된, 데이터를 querystring body부분을 통해 전달받음.
        var id = post.id; // 우린 id값도 받았으니, id값도 처리해주어야하므로 id 변수생성.
        var title = post.title;
        var description = post.description;
        fs.rename(`data/${id}`, `data/${title}`, function(error){ //제목을 바꾸는..
          fs.writeFile(`data/${title}`, description, 'utf8', function(error){ //본문을 바꾸는..
            //200 성공,  404 실패, 302 리다이렉션
            response.writeHead(302, {Location: `/?id=${title}`}); //수정한 페이지로 이동..
            response.end(); //화면출력하는부분
          })
        })
      });
      
    //요청한 pathname이 루트값이 아니고, qeuryData.id가 없다면 즉, 오류페이지 실행.    
    } else {
      response.writeHead(404); // 페이지가 정상적으로 출력되면 200, 오류페이지면 404.
      response.end('NOT FOUND'); //화면출력하는부분
    }

});
app.listen(3000); // 3000번 포트를 서버로 사용하겠다. 선언.

 

- E N D -