쿼리 수행
이전 포스트에서 작성한 코드들로 사용자 정보를 등록하고, 사용자가 등록한 댓글을 가져오는 서버를 만들어 보자.
우선 view부터 작성하자.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>시퀄라이즈 서버</title>
<style>
table { border: 1px solid black; border-collapse: collapse;}
table th, table td { border: 1px solid black;}
</style>
</head>
<body>
<div>
<form id="user-form">
<fieldset>
<legend>사용자 등록</legend>
<div><input id="username" type="text" placeholder="이름"></div>
<div><input id="age" type="number" placeholder="나이"></div>
<div><input id="married" type="checkbox"><label for="married">결혼여부</label></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="user-list">
<thead>
<tr>
<th>아이디</th>
<th>이름</th>
<th>나이</th>
<th>결혼여부</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{'기혼' if user.married else '미혼'}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<div>
<form id="comment-form">
<fieldset>
<legend>댓글 등록</legend>
<div><input id="userid" type="text" placeholder="사용자 아이디"></div>
<div><input id="comment" type="text" placeholder="댓글"></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="comment-list">
<thead>
<tr>
<th>아이디</th>
<th>작성자</th>
<th>댓글</th>
<th>수정</th>
<th>삭제</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="/sequelize.js"></script>
</body>
</html>
views/sequelize.html
<h1>{{ message }}</h1>
<h2>{{ error.status }}</h2>
<pre>{{ error.stack }}</pre>
views/error.html
이제 sequelizejs 파일도 만들자.
//사용자 이름을 눌렀을 때 댓글 로딩
document.querySelectorAll('#user-list tr').forEach((el) => {
el.addEventListener('click', function() {
const id = el.querySelector('td').textContent;
console.log(id);
getComment(id);
});
});
//사용자 로딩
async function getUser(){
try{
const res = await axios.get('/users');
const users = res.data;
console.log(users);
const tbody = document.querySelector('#user-list tbody');
tbody.innerHTML = '';
users.map(function (user){
const row = document.createElement('tr');
row.addEventListener('click', () => {
getComment(user.id);
});
//로우 셀 추가
let td = document.createElement('td');
td.textContent = user.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.age;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.married ? '기혼' : '미혼';
row.appendChild(td);
tbody.appendChild(row);
});
}catch (err){
console.error(err);
}
}
//댓글 로딩
async function getComment(id){
try{
const res = await axios.get(`/users/${id}/comments`);
const comments = res.data;
const tbody = document.querySelector('#comment-list tbody');
tbody.innerHTML = '';
comments.map(function (comment){
const row = document.createElement('tr');
let td = document.createElement('td');
td.textContent = comment.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.User.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.comment;
row.appendChild(td);
const edit = document.createElement('button');
edit.textContent = '수정';
edit.addEventListener('click', async () => { //수정 클릭 시
const newComment = prompt('바꿀 내용을 입력하세요');
if(!newComment){
return alert('내용을 입력하세요');
}
try{
await axios.patch(`/comments/${comment.id}`, { comment: newComment });
getComment(id);
}catch(err){
console.error(err);
}
});
const remove = document.createElement('button');
remove.textContent = '삭제';
remove.addEventListener('click', async () => { //삭제 클릭 시
try{
await axios.delete(`/cmments/${comment.id}`);
getComment(id);
}catch(err){
console.error(err);
}
});
//버튼 추가
td = document.createElement('td');
td.appendChild(edit);
row.appendChild(td);
td = document.createElement('td');
td.appendChild(remove);
row.appendChild(td);
tbody.appendChild(row);
});
}catch (err){
console.error(err);
}
}
//사용자 등록 시
document.getElementById('user-form').addEventListener('submit', async (e) => {
e.preventDefault();
const name = e.target.username.value;
const age = e.target.age.value;
const married = e.target.married.value;
if(!name){
return alert('이름을 입력하세요');
}
if(!age){
return alert('나이를 입력하세요');
}
try{
await axios.post('/users', {name, age, married});
getUser();
}catch(err){
console.error(err);
}
e.target.username.value = '';
e.target.age.value = '';
e.target.married.value = false;
});
//댓글 등록시
document.getElementById('comment-form').addEventListener('submit', async (e) => {
e.preventDefault();
const id = e.target.userid.value;
const comment = e.target.comment.value;
if(!id){
return alert('아이디를 입력하세요');
}
if(!comment){
return alert('댓글을 입력하세요');
}
try{
await axios.post('/comments', { id, comment });
getComment(id);
}catch(err){
console.error(err);
}
e.target.userid.value = '';
e.target.comment.value = '';
});
public/sequelizejs
이제 라우터를 만들고 연결하면 된다.
미리 app에 연결해두자.
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);
const express = require('express');
const User = require('../models/user');
const router = express.Router();
router.get('/', async (req, res, next) => {
try{
const users = await User.findAll();
res.render('sequelize', { users});
}catch(err){
console.error(err);
next(err);
}
});
module.exports = router;
routes/index.js
GET /으로 접속했을 때 라우터이다. User.findAll 메서드로 모든 사용자를 찾은 후 sequelize.html을 렌더링 할 때 결괏값인 users를 넣는다.
시퀄라이즈는 프로미스를 기본적으로 지원하므로 async/await과 try/catch문을 사용해서 각각 조회 성공 시와 실패 시의 정보를 얻을 수 있다.
const express = require('express');
const User = require('../models/user');
const Comment = require('../models/comment');
const router = express.Router();
router.route('/')
.get(async (req, res, next) => {
try {
const user = await User.findAll();
res.json(user);
}catch (err){
console.error(err);
next(err);
}
})
.post(async (req, res, next) => {
try{
const user = await User.create({
name: req.body.name,
age: req.body.age,
married: req.body.married,
});
console.log(user);
res.status(201).json(user);
}catch (err) {
console.log(err);
next(err);
}
});
router.get('/:id/comments', async (req, res, next) => {
try{
const comments = await Comment.findAll({
include: {
model: User,
where: {id: req.params.id},
},
});
console.log(comments);
res.json(comments);
}catch(err){
console.error(err);
}
});
module.exports = router;
routes/users.js
GET /users와 POST /users 주소로 요청이 들어올 때의 라우터이다. 각각 사용자를 조회하는 요청과 사용자를 등록하는 요청을 처리한다.
GET /users/:id/comments 라우터에는 findAll 메서드에 옵션을 추가했다. include 옵션으로 User model을 where 속성에는 :id로 받은 아이디 값을 넣어서 데이터베이스에서 찾는다.
const express = require('express');
const { User, Comment} = require('../models');;
const router = express.Router();
router.post('/', async(req, res, next) => {
try{
const comment = await Comment.create({
commenter: req.body.id,
comment: req.body.comment,
});
console.log(comment);
res.status(201).json(comment);
}catch(err){
console.error(err);
next(err);
}
});
router.route('/:id')
.patch(async (req, res, next) => {
try{
const result = await Comment.update({
comment: req.body.comment,
}, {
where: {id: req.params.id},
});
res.json(result);
}catch(err){
console.error(err);
next(err);
}
})
.delete(async(req, res, next) => {
try{
const result = await Comment.destroy({ where: { id: req.params.id}});
res.json(result);
}catch(err){
console.error(err);
next(err);
}
});
module.exports = router;
routes/comments.js
댓글과 관련된 CRUD 작업을 하는 라우터이다. POST /comments, PATCH/comments/:id, DELETE/comments/:id를 등록했다.
이제 서버를 실행해서 테스트해보자.

사용자의 이름을 누르면 댓글이 나온다.

사용자와 댓글을 추가해보자.

쿼리 수행
이전 포스트에서 작성한 코드들로 사용자 정보를 등록하고, 사용자가 등록한 댓글을 가져오는 서버를 만들어 보자.
우선 view부터 작성하자.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>시퀄라이즈 서버</title>
<style>
table { border: 1px solid black; border-collapse: collapse;}
table th, table td { border: 1px solid black;}
</style>
</head>
<body>
<div>
<form id="user-form">
<fieldset>
<legend>사용자 등록</legend>
<div><input id="username" type="text" placeholder="이름"></div>
<div><input id="age" type="number" placeholder="나이"></div>
<div><input id="married" type="checkbox"><label for="married">결혼여부</label></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="user-list">
<thead>
<tr>
<th>아이디</th>
<th>이름</th>
<th>나이</th>
<th>결혼여부</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{'기혼' if user.married else '미혼'}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<div>
<form id="comment-form">
<fieldset>
<legend>댓글 등록</legend>
<div><input id="userid" type="text" placeholder="사용자 아이디"></div>
<div><input id="comment" type="text" placeholder="댓글"></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="comment-list">
<thead>
<tr>
<th>아이디</th>
<th>작성자</th>
<th>댓글</th>
<th>수정</th>
<th>삭제</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="/sequelize.js"></script>
</body>
</html>
views/sequelize.html
<h1>{{ message }}</h1>
<h2>{{ error.status }}</h2>
<pre>{{ error.stack }}</pre>
views/error.html
이제 sequelizejs 파일도 만들자.
//사용자 이름을 눌렀을 때 댓글 로딩
document.querySelectorAll('#user-list tr').forEach((el) => {
el.addEventListener('click', function() {
const id = el.querySelector('td').textContent;
console.log(id);
getComment(id);
});
});
//사용자 로딩
async function getUser(){
try{
const res = await axios.get('/users');
const users = res.data;
console.log(users);
const tbody = document.querySelector('#user-list tbody');
tbody.innerHTML = '';
users.map(function (user){
const row = document.createElement('tr');
row.addEventListener('click', () => {
getComment(user.id);
});
//로우 셀 추가
let td = document.createElement('td');
td.textContent = user.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.age;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.married ? '기혼' : '미혼';
row.appendChild(td);
tbody.appendChild(row);
});
}catch (err){
console.error(err);
}
}
//댓글 로딩
async function getComment(id){
try{
const res = await axios.get(`/users/${id}/comments`);
const comments = res.data;
const tbody = document.querySelector('#comment-list tbody');
tbody.innerHTML = '';
comments.map(function (comment){
const row = document.createElement('tr');
let td = document.createElement('td');
td.textContent = comment.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.User.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.comment;
row.appendChild(td);
const edit = document.createElement('button');
edit.textContent = '수정';
edit.addEventListener('click', async () => { //수정 클릭 시
const newComment = prompt('바꿀 내용을 입력하세요');
if(!newComment){
return alert('내용을 입력하세요');
}
try{
await axios.patch(`/comments/${comment.id}`, { comment: newComment });
getComment(id);
}catch(err){
console.error(err);
}
});
const remove = document.createElement('button');
remove.textContent = '삭제';
remove.addEventListener('click', async () => { //삭제 클릭 시
try{
await axios.delete(`/cmments/${comment.id}`);
getComment(id);
}catch(err){
console.error(err);
}
});
//버튼 추가
td = document.createElement('td');
td.appendChild(edit);
row.appendChild(td);
td = document.createElement('td');
td.appendChild(remove);
row.appendChild(td);
tbody.appendChild(row);
});
}catch (err){
console.error(err);
}
}
//사용자 등록 시
document.getElementById('user-form').addEventListener('submit', async (e) => {
e.preventDefault();
const name = e.target.username.value;
const age = e.target.age.value;
const married = e.target.married.value;
if(!name){
return alert('이름을 입력하세요');
}
if(!age){
return alert('나이를 입력하세요');
}
try{
await axios.post('/users', {name, age, married});
getUser();
}catch(err){
console.error(err);
}
e.target.username.value = '';
e.target.age.value = '';
e.target.married.value = false;
});
//댓글 등록시
document.getElementById('comment-form').addEventListener('submit', async (e) => {
e.preventDefault();
const id = e.target.userid.value;
const comment = e.target.comment.value;
if(!id){
return alert('아이디를 입력하세요');
}
if(!comment){
return alert('댓글을 입력하세요');
}
try{
await axios.post('/comments', { id, comment });
getComment(id);
}catch(err){
console.error(err);
}
e.target.userid.value = '';
e.target.comment.value = '';
});
public/sequelizejs
이제 라우터를 만들고 연결하면 된다.
미리 app에 연결해두자.
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);
const express = require('express');
const User = require('../models/user');
const router = express.Router();
router.get('/', async (req, res, next) => {
try{
const users = await User.findAll();
res.render('sequelize', { users});
}catch(err){
console.error(err);
next(err);
}
});
module.exports = router;
routes/index.js
GET /으로 접속했을 때 라우터이다. User.findAll 메서드로 모든 사용자를 찾은 후 sequelize.html을 렌더링 할 때 결괏값인 users를 넣는다.
시퀄라이즈는 프로미스를 기본적으로 지원하므로 async/await과 try/catch문을 사용해서 각각 조회 성공 시와 실패 시의 정보를 얻을 수 있다.
const express = require('express');
const User = require('../models/user');
const Comment = require('../models/comment');
const router = express.Router();
router.route('/')
.get(async (req, res, next) => {
try {
const user = await User.findAll();
res.json(user);
}catch (err){
console.error(err);
next(err);
}
})
.post(async (req, res, next) => {
try{
const user = await User.create({
name: req.body.name,
age: req.body.age,
married: req.body.married,
});
console.log(user);
res.status(201).json(user);
}catch (err) {
console.log(err);
next(err);
}
});
router.get('/:id/comments', async (req, res, next) => {
try{
const comments = await Comment.findAll({
include: {
model: User,
where: {id: req.params.id},
},
});
console.log(comments);
res.json(comments);
}catch(err){
console.error(err);
}
});
module.exports = router;
routes/users.js
GET /users와 POST /users 주소로 요청이 들어올 때의 라우터이다. 각각 사용자를 조회하는 요청과 사용자를 등록하는 요청을 처리한다.
GET /users/:id/comments 라우터에는 findAll 메서드에 옵션을 추가했다. include 옵션으로 User model을 where 속성에는 :id로 받은 아이디 값을 넣어서 데이터베이스에서 찾는다.
const express = require('express');
const { User, Comment} = require('../models');;
const router = express.Router();
router.post('/', async(req, res, next) => {
try{
const comment = await Comment.create({
commenter: req.body.id,
comment: req.body.comment,
});
console.log(comment);
res.status(201).json(comment);
}catch(err){
console.error(err);
next(err);
}
});
router.route('/:id')
.patch(async (req, res, next) => {
try{
const result = await Comment.update({
comment: req.body.comment,
}, {
where: {id: req.params.id},
});
res.json(result);
}catch(err){
console.error(err);
next(err);
}
})
.delete(async(req, res, next) => {
try{
const result = await Comment.destroy({ where: { id: req.params.id}});
res.json(result);
}catch(err){
console.error(err);
next(err);
}
});
module.exports = router;
routes/comments.js
댓글과 관련된 CRUD 작업을 하는 라우터이다. POST /comments, PATCH/comments/:id, DELETE/comments/:id를 등록했다.
이제 서버를 실행해서 테스트해보자.

사용자의 이름을 누르면 댓글이 나온다.

사용자와 댓글을 추가해보자.
