궤도

[백엔드] Node.js에서 sequelize를 활용하여 CRUD 구현하기[1] 본문

💻 현생/📃 VIVA

[백엔드] Node.js에서 sequelize를 활용하여 CRUD 구현하기[1]

영이오 2021. 2. 1. 21:19

지난 시간에 sequelize를 이용하여 기존에 만들어둔 DB를 연동하는 것까지 성공했다.

이제 DB의 가장 기본이라고 할 수 있는 create, read, update, delete 즉, CRUD를 해보도록 하겠다.

이 과정에서 내가 한 뻘짓들은 수치스러워서 말하기도 부끄럽지만 공익을 위해 작성한다.

 

victorydntmd.tistory.com/29

 

[Node.js] sequelize(3) - CRUD + RESTful 게시판 만들기

2019. 07. 21 수정 이전 글에서 sequelize에 대한 기본 개념을 알아보았습니다. 이번 글에서는 sequelize를 이용하여 게시판을 만들어보겠습니다. 개발환경 express-generator 4.16.1 MySQL 8.0.16 sequelize 5.1..

victorydntmd.tistory.com

오늘 함께할 블로그이다. 참고로 아는게 없어서 설명은 거의 안하고 내 테이블에 맞춰 따라하는게 대부분이기 때문에 그냥 해당 블로그를 따라하다가 막히는 부분이 있을 때 이 글을 참고하는 것을 추천한다. 물론 우리가 같은 오류를 겪었을 지는 알 수 없지만.

 

우린 지금 회원가입-로그인을 구현하는 중이니까 회원 정보를 담은 student 테이블을 이용할 것이다.


Create

먼저 저 블로그 처럼 view 폴더 아래에 show.ejs 파일을 만들자

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <h1>회원 추가하기</h1>
    <hr>

    <form action="/board" method="POST">
        <table>
            <tr>
                <td><input type="text" name="inputId" placeholder="아이디를 입력하세요."></td>
            </tr>
            <tr>
                <td><input type="password" name="inputPw" placeholder="비밀번호를 입력하세요."></td>
            </tr>
            <tr>
                <td><input type="text" name="inputNick" placeholder="닉네임을 입력하세요."></td>
            </tr>
            <tr>
                <td>
                    <select name="inputGrade">
                        <option value="1">1학년</option>
                        <option value="2">2학년</option>
                        <option value="3">3학년</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td><input type="text" name="inputPic" placeholder="이미지를 입력하세요."></td>
            </tr>
        </table>
        <input type="submit" value="전송하기">
    </form>
</body>

</html>

비밀번호를 받을 때는 input type을 password로 해서 보이지 않게 했고,

학년은 1~3학년 중 하나를 고르게 하기 위해 select로 처리했다.

 

var express = require('express');
var router = express.Router();

router.get('/board', function(req, res, next) {
  res.render('show');
});

module.exports = router;

그 다음에 routes/index.js 파일에 경로를 등록한다.

저 res.render('show')가 뭘까 찾아보니 show.ejs와 연결한다는 뜻이라고 한다. 내가 이렇게 아는게 없다.

 

localhost:3000/board 로 들어가면 이렇게 잘 나온다.

상당히 못생겼지만 어쩔 수 없다. 우린 백엔드다.

 

이제 form으로 넘겨받은 데이터를 처리하자

 

var express = require('express');
var models = require('../models');
var router = express.Router();

router.get('/board', function(req, res, next) {
  res.render('show');
});

router.post('/board', function(req, res, next){
  let body = req.body;

  models.student.create({
    stu_id: body.inputId,
    stu_pw: body.inputPw,
    stu_nick: body.inputNick,
    stu_grade: body.inputGrade,
    stu_photo: body.inputPic
  })
  .then(result => {
    console.log("success");
    res.redirect('/board');
  })
  .catch(err => {
    console.log(err);
  })
});

module.exports = router;

다시 routes/index.js다. 앞서 form에서 받은 inputId, inputPw...를 그대로 테이블에 해당하는 칼럼인 stu_id, stu_pw...에 넣어준다. 이게 sequelize 문법이라나보다.

성공하면 다시 /board로 리다이렉트 했고, 실패시 실패 이유를 알기 위해 에러 메세지를 출력하도록 했다.

 

 

잘 들어왔다. 지금 기술이 부족해서 이미지는 링크로 받고 있다.

아 그리고 칼럼명에 대문자가 있었을 때 sequelize에서 오류를 뱉어냈다. 이유는 모르겠지만 소문자로 바꾸니까 해결됐다.


Read

    <table>
        <tr>
            <td>아이디</td>
            <td>닉네임</td>
            <td>학년</td>
            <td>프로필 사진</td>
        </tr>
        <% for(let post of students) { %>
            <tr>
                <td>
                    <%= post.stu_id %>
                </td>
                <td>
                    <%= post.stu_nick %>
                </td>
                <td>
                    <%= post.stu_grade %>
                </td>
                <td>
                    <img src="<%= post.stu_photo %>" width="70" height="70"/>
                </td>
            </tr>
            <% } %>
    </table>

테이블 형태로 데이터를 출력할 것이다. 근데 저기서 students 변수가 도대체 어디서 나온 것이냐 한다면

 

router.get('/board', function(req, res, next){
  models.student.findAll()
  .then(result =>{
    res.render('show', {
      students: result
    });
  })
  .catch(function(err){
    console.log(err);
  });
});

여기서 나온 것이다. routes/index.js에서 앞서 작성한 짧은 router.get을 이렇게 수정한 것이다.

result를 저장한 student는 따로 부르지 않아도 show.ejs에서 넘겨진다고 한다.

 

근데, 난 여기서 발생한 오류로 며칠을 고생했다. 그리고 오류의 원인은 터무니 없었다.

npm install ejs --save

ejs를 install 하지 않아서 ejs의 문법을 인식하지 못한 것이다. 정말 어이없는 실수였다.

 

아무튼 이제 잘 나온다.


Update

    <table>
        <tr>
            <td>아이디</td>
            <td>닉네임</td>
            <td>학년</td>
            <td>프로필 사진</td>
        </tr>
        <% for(let post of students) { %>
            <tr>
                <td>
                    <%= post.stu_id %>
                </td>
                <td>
                    <%= post.stu_nick %>
                </td>
                <td>
                    <%= post.stu_grade %>
                </td>
                <td>
                    <img src="<%= post.stu_photo %>" width="70" height="70"/>
                </td>
                <td><button ><a href="/edit/<%=post.stu_sn%>">수정하기</a></button></td>
            
                <form action="/edit/<%=post.stu_sn%>?_method=DELETE" method="post">
                    <td><input type="submit" value="삭제하기"></input></td>
                </form>
            </tr>
            <% } %>
    </table>

view/show.ejs 파일에 수정하기와 삭제하기 버튼을 추가한다. 참고로 위 블로그에 오타가 있다.

수정하기 버튼에서 /board/라고 써있는데 /edit/으로 해야한다.

 

router.get('/edit/:id', function(req, res, next) {
  let postID = req.params.id;

  models.student.findOne({
    where: {stu_sn: postID}
  })
  .then( result => {
    res.render("edit", {
      post: result
    });
  })
  .catch( err => {
    console.log(err);
  });
});

그리고 routes/index.js에 이런 것도 추가하고

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<h1>회원정보 수정</h1>
<hr>

<form action="/board/<%= post.stu_sn %>?_method=PUT" method="post">
    <table>
        <tr>
            <td><input type="text" name="editId" value="<%= post.stu_id %>"></td>
        </tr>
        <tr>
            <td><input type="password" name="editPw" value="<%= post.stu_pw %>"></td>
        </tr>
        <tr>
            <td><input type="text" name="editNick" value="<%= post.stu_nick %>"></td>
        </tr>
        <tr>
            <td>
                <select name="editGrade">
                    <option value="1">1학년</option>
                    <option value="2">2학년</option>
                    <option value="3">3학년</option>
                </select>
            </td>
        </tr>
        <tr>
            <td><input type="text" name="editPic" value="<%= post.stu_photo %>"></td>
        </tr>
    </table>
    <input type="submit" value="전송하기">
</form>
</body>
</html>

view 폴더에 edit.ejs도 추가하고...

 

method-override 모듈도 설치해서 app.js에 추가도 하고...

 

router.put('/board/:id', function(req, res, next) {
  let postID = req.params.id;
  let body = req.body;

  models.student.update({
    stu_id: body.editId,
    stu_pw: body.editPw,
    stu_nick: body.editNick,
    stu_grade: body.editGrade,
    stu_photo: body.editPic
  },{
    where: {stu_sn: postID}
  })
  .then( result => {
    console.log("데이터 수정 완료");
    res.redirect("/board");
  })
  .catch( err => {
    console.log(err);
  });
});

routes/index.js에 이런 것도 추가하면...

 

잘된다. 왜 위에 있는 수정이미지는 vivaaaa인데 결과는 viaaa인지 의문을 품는다면 그냥 오타다.

pk만 잘 신경쓰면 큰 문제 없을 것이다.


Delete

router.delete('/board/:id', function(req, res, next) {
  let postID = req.params.id;

  models.student.destroy({
    where: {stu_sn: postID}
  })
  .then( result => {
    res.redirect("/board")
  })
  .catch( err => {
    console.log(err);
  });
});

routes/index.js에 이런걸 추가하고

 

삭제버튼이 잘 작동하는 것을 볼 수 있다.


잘 안되는 것 같을 때

1. ctrl+C 한 뒤 다시 npm start를 한다.

2. 오타 없는지 확인한다.

3. pk 잘 조작하고 있는지 확인한다.

 

근데 우리는 백엔드고 저 화면이 프론트가 될 건 아니지 않은가?

그러니 다음 시간엔 얘네들을 api로 뽑아내서 프론트가 쓸 수 있게 바꿔보자

Comments