[MYSQL] 웹 앱 제작하기 - 삭제

jihan kong·2022년 3월 28일
0

MySQL 

목록 보기
9/9
post-thumbnail

삭제기능 구현

드디어 CRUD 중 마지막 "삭제" 기능까지 왔다. 지금까지 우리는 간단하지만 웹을 통해 내가 원하는 내용으로 글 제목(title)내용(description) 을 추가하고 이를 웹에 출력했고, 다시 이것을 edit하는 기능을 구현했다. 삭제까지 구현하게 되면 간단한 웹 서버의 형태를 갖출 수 있게 된다.

1. delete 버튼 생성

먼저, delete 버튼을 추가하기 위해 view.pug 을 열어보자.

view.pug

    ul
      li
        a(href='/topic/add') add
      if topic
        li
          a(href='/topic/'+topic.id+'/edit') edit

li 태그를 통해 만약 topic.id 로 들어왔다면 delete 할 수 있도록 버튼을 만들 것이기 때문에 edit 코드 밑에 다음의 한 줄을 추가한다.

        li
         a(href='/topic/'+topic.id+'/delete') delete

앱을 실행하고 아무 목록이나 눌러보면

delete 버튼이 잘 생성이 되었다.

2. router 구현 - (1)

이제 삭제를 위한 라우터를 만들어보자. 먼저 /topic/:id/delete 로 들어왔을 때, 서버의 기능을 해줄 라우터를 생성할 것이다.

app.get('/topic/:id/delete', function(req, res){
  var sql = 'SELECT id, title FROM topic';
  var id = req.params.id;
  conn.query(sql, function(err, topics, fields){
    var sql = 'SELECT * FROM topic WHERE id=?';
    conn.query(sql, [id], function(err, topic) {
      if(err) {
        console.log(err);
        res.status(500).send('Internal Server Error');
      } else {
        if(topic.length == 0){
          console.log('There is no record');
          res.status(500).send('Internal Server Error');
        } else {
         res.render('delete', {topics:topics, topic:topic[0]});
        }
      }
    });
  });
});

위 코드를 보면 알 수 있듯, 삭제 기능은 다른 라우터보다 조금 더 생각할 것이 있다. 우선 SELECT 문을 통해 idtitle 로 조회할 수 있도록 하고 topic/id(숫자) 로 접속한 사용자에 대해서 다음의 로직을 구성한다.

  1. 서버 접속 에러 --> Internal Server Error 전송
  2. 서버는 접속 했지만 잘못된 (없는) topic/id 로 접속했을 경우
    --> There is no record 출력, Internal Server Error 전송
  3. 정상 접속 --> 미리 생성한 delete 를 렌더링 해줌

3. delete 기능 구현

add.pug 를 복사해서 delete.pug 를 생성한다. 그리고 article 태그 밑의 내용을 모두 날리고 delete 기능을 구현해보자.

일단 delete 버튼을 눌렀을 때, 아이템(글 리스트)을 바로 삭제하는 것은 너무 야박(?)하다. 따라서 delete를 실행했을 때, 과연 정말 삭제할 것인지 확인하는 절차를 마련해놓기로 하자.

delete.pug

html
  head
    meta(charset='utf-8')
  body
    h1
      a(href='/topic') Server Side JavaScript
    ul
      each topic in topics
        li
          a(href='/topic/'+topic.id)= topic.title
    article
      h1= 'Delete? ' + topic.title
      a(href='/topic/'+topic.id+'/delete') yes
      a(href='/topic/'+topic.id) no

이렇게 하게 되면 topic의 title에 해당하는 글 안에서 delete 를 눌렀을 때, title을 띄우고 "지울 것인가(yes)" 또는 "지우지 않을 것인가 (No)" 를 사용자에게 선택할 수 있도록 해준다.

잘 작동되는 모습이다.

이제 이를 토대로 조금 더 구체적으로 구현시켜보자.

 article
   h1= 'Delete? ' + topic.title
      form(action='/topic/'+topic.id+'/delete' method='post')
        p
         input(type='submit' value='YES')
    a(href='/topic/'+topic.id) NO

a(href='/topic/'+topic.id) yes 의 내용을 form 태그의 action 속성을 통해 topic.id 에 해당하는 내용을 post 방식으로 delete 할 수 있게끔 바꾸어 준다.

여기서 드는 궁금증은 왜 get 방식이 아닌 post 방식을 사용했을까?

get 방식은 아무래도 보안상 확실히 취약점이 있다고 했다. 더더욱 글의 내용을 수정하거나 삭제하는 작업은 외부에서 어떠한 주소의 파라미터값으로 내가 작성한 글에 접근할 수 없도록 하는 것이 중요한데, 이를 위해선 get이 아닌 post가 적합하다. 따라서 일반적으로 글을 수정, 삭제할 때는 post 방식을 사용한다.

또한 p 태그 밑 input 값의 submit type으로 제출 버튼을 만들고 값은 YES.
즉, '삭제' 를 구현하고

링크로 이동하는 href 속성으로 NO. '삭제하지 않고 다시 본문의 내용으로 돌아가기' 의 내용을 구현한다.

router 구현 - (2)

이제, app_mysql 로 돌아가서 topic/:id/delete 즉, 실제 sql문을 통해 delete 기능을 수행해줄 라우터를 구현하자.

app_mysql

app.post('/topic/:id/delete', function(req, res){
  var id = req.params.id;
  var sql = 'DELETE FROM topic WHERE id=?';
  conn.query(sql, [id], function(err, result) {
    res.redirect('/topic/');
  });
});

위에서 언급한대로 post 방식으로 기능을 수행하기로 했었고, id 변수를 통해 id 값을 요청한다. 또한 conn.query 를 통해 sql문과 id값을 연결시키고 마지막으로 미들웨어에서 res의 메소드로 redirect를 사용하여 삭제 후, /topic 의 내용으로 이동하게끔 해준다.

드디어 삭제를 위한 모든 작업이 끝났다. 앱을 실행해보자.

리스트에서 delete 를 누르고 no를 눌렀을 경우, 이전으로 돌아가고 YES를 누르면 삭제가 되는 것을 볼 수 있다.

후기

생활코딩 강의를 통해 아주 심플하지만 그래도 잘 작동하는 웹 앱을 만들어보았다. 실제로 요즘 웹 앱은 React나 typescript로 프론트도 잘 구현되어있고, 백엔드도 API를 통해 인터페이스를 좀 더 복잡한 구조로 구성하고 있겠지만 node와 DB 즉, mysql만 가지고도 기본적으로 서버와 클라이언트가 정보를 주고받는 웹 앱을 구현했다는 점에서 의의가 있다. 여기서 그치지 않고 배운 것을 바탕으로 웹 어플리케이션을 만들고 활용하는 단계까지 올 수 있도록 노력하고 또 노력할 것이다.

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글