공부 저장소/Node.js

[생활코딩 Node.js] 15. 글 수정 기능 만들기

tipsygypsy 2022. 8. 4. 20:47

글 수정(update) 기능 추가하기

애플리케이션의 4대 기본 기능인 CRUD 중에 현재까지 Create, Read까지는 구현한 셈이다. 그러면 당연히 남은 것은 Update와 Delete. 이번에는 글 수정 기능을 추가해 본다.

 

update를 위해서는 당연히 update 링크를 생성해 줘야 하기 때문에, 템플릿에서 해당 부분을 만들어 준다. 그런데 update 링크는 홈 화면이나 create 화면에서는 보일 필요가 없고 특정 글에 들어갔을 때만 보이면 되기 때문에 좀 세부적으로 핸들링해주기 위해 따로 빼서 조건별로 만들어 주기로 한다.

먼저 템플릿 함수에서 create 링크가 있던 부분을 control 변수로 바꿔 주고,

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>
  `;
}

특정 게시물 화면, 즉 쿼리스트링 id가 빈 값이 아닌 경우에, 해당 게시물의 update 링크가 생성되어 보이도록 아래와 같이 설정해 준다.

var template = templateHTML(title, list,
            `<h2>${title}</h2>${description}`,
            `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);

쿼리스트링 id가 빈 값인 경우(=홈 화면)는 update부분을 제외한 create 링크만 설정하고, id가 create인 경우(글 작성 화면)에는 create도 update도 보이지 않는 게 맞기 때문에 control 변수 부분을 공란(’’)으로 처리한다.

 

다음으로는 update 페이지에 들어갔을 때 실제로 보이는 form부분을 만든다.

일단 pathname=/update 인 조건문이 하나 더 필요하므로 else if를 만들어 주고, 기본적인 틀은 create 페이지와 동일하게 생성한다. 다만 update 페이지는 create와 달리 입력칸 안에 수정할 게시물의 제목과 내용이 이미 들어가 있어야 하므로, 각 input태그마다 해당하는 변수를 넣어 준다.

var template = templateHTML(title, list,
          `<form class="" action="/update_process" method="post">
            <p><input type="text" name="title" placeholder="제목" value="${title}"></p>
            <p>
              <textarea name="description" rows="8" cols="60" placeholder="내용">${description}</textarea>
            </p>
            <p>
              <input type="submit" value="수정">
            </p>
          </form>`,
          `<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);

그런데 여기서 한 가지 주의해야 할 점은, 만약 글의 내용이 아닌 제목을 수정한 경우라면 submit하면서 넘어가는 title값은 수정 이후의 값이라는 부분이다. 수정하는 프로세스에서는 원래의 title값을 알아야 해당하는 파일을 수정할 텐데 이미 수정된 값만 알아서는 제대로 수정이 진행될 수가 없다.

이 부분을 컨트롤하기 위해 숨겨진 input을 하나 추가해, 원래의 제목 값을 담고 있도록 세팅해 준다.

<input type="hidden" name="id" value=${title}>

form 데이터가 전송될 때 같이 전송되지만, hidden이므로 화면에 보여지지는 않는다.

 

그러면 이제 create_process와 마찬가지로, 입력한 값을 받아 파일을 생성하고 해당 게시물로 리다이렉션시켜 주는 update_process를 생성한다. 기본적으로는 create_process를 복사해서 사용한다. 다만 아까 히든 id값을 추가해 줬으므로 그 값을 받는 id 변수를 추가한다. 그리고 원래 있던 파일의 파일명을 수정된 파일명으로 교체해야 하기 때문에, fs.rename 함수를 사용한다. 파일명만 바꾸면 안의 내용을 채우는 부분은 create와 동일하므로 그대로 사용하면 된다.

else if(pathname === '/update_process'){
    var body = '';
  request.on('data', function(data){
      body = 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(error){
        fs.writeFile(`data/${title}`, description, 'utf-8', function(err){
        response.writeHead(302, {Location : `/?id=${title}`});
      response.end();
      });    
    });
  });
}

update를 실행해서 파일명과 내용이 잘 바뀌는지, 화면에 잘 반영되는지 확인한다.