궤도
[백엔드] Node.js + Sequelize + MySQL 내 책 리스트를 만들어보자 본문
제목을 뭐라고 하면 좋을지 모르겠어서 저렇게 대충 썼다.
범용성이 떨어지는 제목이 됐으나, 이게 최선이었다. 아무튼 이 게시물에서는 내 책 리스트를 만들 것이다.
사용자가 보유한 책들을 일반교재/학원교재/오답노트로 나눠서 보여주고, 각 책들에 대한 삭제 기능과 오답노트에 대해서는 수정 기능도 넣어줄 것이다. 아 그리고 검색 기능에선 할 수 없던 오답노트 생성 기능도 넣을 것이다.
얘네들을 구현하면 된다는 것이다.
책 리스트 가져오기
사실 이건 이미 했었다.
똑같은 기능을 하는 코드가 이미 있는데 또 만들 이유는 없으니까 app.js에 한줄만 추가해주자
app.js
app.use('/api/book-list', require("./routes/home"));
이렇게 하면 home에 있던 코드를 api/book-list 주소에서도 사용할 수 있다.
localhost:3001/api/home/workbook?stu_id=samdol
localhost:3001/api/book-list/workbook?stu_id=samdol
이 두 주소가 같은 결과를 보여줄 것이란 뜻이다.
localhost:3001/api/book-list/workbook?stu_id=samdol
책 삭제하기
프론트에서 삭제할 교재의 workbook_sn와 사용자의 stu_id를 넘겨주면 이를 기준으로 stu_workbook/incor_note 테이블에서 삭제 작업을 할 것이다. 일반 교재와 학원 교재는 모두 stu_workbook 테이블에 있고 오답노트만 incor_note 테이블에 있기 때문에 일반 교재와 학원 교재의 삭제 코드는 동일하고, 오답노트 삭제 코드만 다르다.
그럼 먼저 일반교재와 학원 교재를 삭제하는 코드부터 보도록 하자.
routes/book-list.js(일반, 학원 교재 삭제)
async function deleteBook(req, res) {
const input_stu_id = req.query.stu_id;
const sn = req.params.sn;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
models.stu_workbook.destroy({
where: {
stu_sn: result.dataValues.stu_sn,
workbook_sn: sn
}
})
.then(num => {
if (num == 1) { //성공
res.send({
message: "Delete book",
status: 'success'
});
} else { //데이터 입력 잘못한듯
res.send({
message: "Data was not found!",
status: 'fail'
});
}
})
.catch(err => { //에러
res.send({
message: "Could not delete book",
status: 'fail'
});
});
}
// Delete
//localhost:3001/api/book-list/workbook/'삭제할 workbook_sn'?stu_id=samdol
router.delete('/workbook/:sn', async function (req, res, next) {
deleteBook(req, res);
});
// Delete
//localhost:3001/api/book-list/academy/'삭제할 workbook_sn'?stu_id=samdol
router.delete('/academy/:sn', async function (req, res, next) {
deleteBook(req, res);
});
보면 알겠지만 deleteBook 함수만 살펴보면 된다.
const input_stu_id = req.query.stu_id;
const sn = req.params.sn;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
늘 하던대로 입력받은 stu_id를 기준으로 사용자를 찾아내어 pk인 stu_sn을 뽑아낸다.
models.stu_workbook.destroy({
where: {
stu_sn: result.dataValues.stu_sn,
workbook_sn: sn
}
})
.then(num => {
if (num == 1) { //성공
res.send({
message: "Delete book",
status: 'success'
});
} else { //데이터 입력 잘못한듯
res.send({
message: "Data was not found!",
status: 'fail'
});
}
})
.catch(err => { //에러
res.send({
message: "Could not delete book",
status: 'fail'
});
});
그리고 stu_sn과 프론트에서 넘어온 workbook_sn(sn)을 이용해 stu_workbook 테이블에서 교재를 삭제하면 된다.
routes/book-list.js(오답노트 삭제)
// Delete
//localhost:3001/api/book-list/incor-note/'삭제할 note_sn'?stu_id=samdol
router.delete('/incor-note/:sn', async function (req, res, next) {
const input_stu_id = req.query.stu_id;
const sn = req.params.sn;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
models.incor_note.destroy({
where: {
stu_sn: result.dataValues.stu_sn,
note_sn: sn
}
})
.then(num => {
if (num == 1) { //성공
res.send({
message: "Delete book",
status: 'success'
});
} else { //데이터 입력을 잘못한듯
res.send({
message: "Data was not found!",
status: 'fail'
});
}
})
.catch(err => { //에러
res.send({
message: "Could not delete book",
status: 'fail'
});
});
});
오답노트는 삭제의 대상이 incor_note 테이블에 있다는걸 제외하고는 동일하다. 그렇기 때문에 굳이 부연 설명을 하지 않겠다.
localhost:3001/api/book-list/workbook/7051?stu_id=samdol
오답노트 정보 수정하기
우리 오답노트에는 수정 기능이 있다. 많이 수정할 수 있는건 아니고 그냥 제목과 표지 정도를 바꿀 수 있다. 해보자
routes/book-list.js(오답노트 수정)
// Update incor-note
//localhost:3001/api/book-list/incor-note/'수정할 note_sn'?stu_id=samdol
router.put('/incor-note/:sn', async function (req, res, next) {
const input_stu_id = req.query.stu_id;
const sn = req.params.sn;
let body = req.body;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
models.incor_note.update({ //이름, 사진 수정
note_name: body.note_name,
note_photo: body.note_photo
}, {
where: {
stu_sn: result.dataValues.stu_sn,
note_sn: sn
}
})
.then(num => {
if (num == 1) { //성공
res.send({
message: "incor_note was updated successfully.",
status: 'success'
});
} else { //데이터 입력 잘못한듯
res.send({
message: "Data was not found or req.body is empty!",
status: 'fail'
});
}
})
.catch(err => { //에러
res.send({
message: "Error updating incor_note",
status: 'fail'
});
console.log(err);
});
});
별거 없지만 설명을 해보자면
const input_stu_id = req.query.stu_id;
const sn = req.params.sn;
let body = req.body;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
늘 하는 stu_id를 stu_sn으로 바꿔주는 과정...
models.incor_note.update({ //이름, 사진 수정
note_name: body.note_name,
note_photo: body.note_photo
}, {
where: {
stu_sn: result.dataValues.stu_sn,
note_sn: sn
}
})
update...
.then(num => {
if (num == 1) { //성공
res.send({
message: "incor_note was updated successfully.",
status: 'success'
});
} else { //데이터 입력 잘못한듯
res.send({
message: "Data was not found or req.body is empty!",
status: 'fail'
});
}
})
.catch(err => { //에러
res.send({
message: "Error updating incor_note",
status: 'fail'
});
console.log(err);
});
결과 처리...
오답노트 생성하기
오답노트는 홈 화면에서 생성할 수도 있고, 교재 리스트에서 생성할 수도 있다. 그래서 home.js 파일에 만들기로 했다.
//localhost:3001/api/home/incor-note?stu_id=samdol
//localhost:3001/api/book-list/incor-note?stu_id=samdol
router.post('/incor-note', async function (req, res, next) {
const input_stu_id = req.query.stu_id;
let body = req.body;
let result = await models.student.findOne({
where: {
stu_id: input_stu_id
}
});
models.incor_note.create({ //이름, 사진, 학생 입력함. 생성 날짜는 자동으로 들어감
stu_sn: result.dataValues.stu_sn,
note_name: body.note_name,
note_photo: body.note_photo
})
.then(result => {
res.send({
message: 'Inserted in DB',
status:'success',
data:{ //result는 그냥 내가 postman에서 보려고 넣은거라 실제로 쓸 때는 빼도 괜찮음.
result
}
})
})
.catch(err => { //무슨 문제가 생겼을까...
res.send({
message:
err.message || "Some error occurred while insert data.",
status:'fail'
});
});
});
거의 update가 create로 바뀐 수준의 차이라 굳이 설명할 필요 없을 것 같다. 다만 오답노트 생성시에는 이 노트를 소유하고 있는 학생을 명시해야 하니 stu_sn을 받아야 한다.
localhost:3001/api/book-list/incor-note?stu_id=samdol