AJAX 방식의 비동기통신 & 서버 분리 & MVC패턴을 적용한 댓글 CRUD 예제코드입니다
프론트 서버 설치 모듈 : express, nunjucks
백엔드 서버 설치 모듈 : express, cors, (cookie-parser)
[server]
const express = require("express");
const cors = require("cors");
const app = express();
const router = require("./routes/index.route");
const cookieParser = require("cookie-parser");
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(router);
app.use((err, req, res, next) => {
console.log(err.message);
res.send(`ERROR ${err}`);
});
app.listen(3000, () => {
console.log("backend listening on port 3000");
});
[route]
// index
const express = require("express");
const router = express.Router();
const comments = require("../comments/comment.route");
router.use("/comments", comments);
module.exports = router;
// comments
const express = require("express")
const router = express.Router()
const controller = require("./comment.controller")
router.get("/", controller.getComments)
router.get("/:id", controller.getComment)
router.post("/", controller.postComments)
// router.put("/:id", controller.putComments)
router.delete("/:id", controller.deleteComments)
module.exports = router
[repository]
const pool = require("../db.js");
exports.findAll = async () => {
const [sql] = await pool.query(`SELECT * FROM Comments ORDER by id DESC;`)
return sql
}
// this.findAll().then(v=>console.log(v))
exports.addComment = async ({ userid, content }) => {
const sql = `INSERT INTO Comments(userid, content) VALUES('${userid}','${content}')`;
await pool.query(sql);
};
exports.updateComment = async ({ id, content }) => {
const sql = `UPDATE Comments SET content = '${content}' WHERE id = '${id}'`;
await pool.query(sql);
};
exports.deleteComment = async (id) => {
const sql = `DELETE FROM Comments WHERE id=$'{id}'`;
await pool.query(sql);
};
프론트엔드 쪽은 클라이언트의 자바스크립트가 할 일이 많아졌네요
요청 메서드와 라우터 경로에 맞게 req.body에 실어보낼 내용을 잘 전달하면 끝!
const commentFrm = document.querySelector("#commentFrm");
const request = ({ method, path, body }) => {
return new Promise((resolve, reject) => {
const host = `http://localhost:3000`;
const xhr = new XMLHttpRequest();
xhr.open(method, `${host}${path}`);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(body));
xhr.onload = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error("Error"));
}
};
});
};
window.addEventListener("load", async () => {
const comments = await request({
method: "GET",
path: "/comments",
});
const commentList = document.querySelector("#comment-list");
for (const comment of comments) {
const commentRow = document.createElement("li");
commentRow.innerHTML = `
<span class="comment-id">${comment.id}</span>
<span class="comment-userid">${comment.userid}</span>
<span class="comment-content">${comment.content}</span>
<span class="comment-register">${comment.register}</span>
<button class="comment-modify">수정</button>
<button class="comment-delete">삭제</button>
`;
commentList.appendChild(commentRow);
}
const submit = document.querySelector(".btn");
submit.addEventListener("click", async () => {
const userid = "nazzzo";
const content = document.querySelector(".int").value;
await request({
method: "POST",
path: "/comments",
body: { userid, content },
});
});
const id = document.querySelector("#comment-id").innerHTML;
const dltComment = document.querySelector(".comment-delete");
dltComment.addEventListener("click", async () => {
await request({
method: "DELETE",
path: "/comments/:id",
body: id,
});
});
});