궤도
[백엔드] Node.js에서 sequelize를 활용하여 CRUD 구현하기[1] 본문
지난 시간에 sequelize를 이용하여 기존에 만들어둔 DB를 연동하는 것까지 성공했다.
이제 DB의 가장 기본이라고 할 수 있는 create, read, update, delete 즉, CRUD를 해보도록 하겠다.
이 과정에서 내가 한 뻘짓들은 수치스러워서 말하기도 부끄럽지만 공익을 위해 작성한다.
오늘 함께할 블로그이다. 참고로 아는게 없어서 설명은 거의 안하고 내 테이블에 맞춰 따라하는게 대부분이기 때문에 그냥 해당 블로그를 따라하다가 막히는 부분이 있을 때 이 글을 참고하는 것을 추천한다. 물론 우리가 같은 오류를 겪었을 지는 알 수 없지만.
우린 지금 회원가입-로그인을 구현하는 중이니까 회원 정보를 담은 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로 뽑아내서 프론트가 쓸 수 있게 바꿔보자