router.get('/', (req, res) => {
// res.render('index');
res.redirect('/posts');
});
router.get('/', async (req, res, next) => {
// 게시글 목록
const posts = await Post.find({}).exec();
res.render('post/list', { posts });
});
router.get('/:shortId', async (req, res, next) => {
const { shortId } = req.params;
// shortId 로 게시글 찾기
const post = await Post.findOne({shortId}).exec();
res.render('post/view', { post });
});
router.post('/', async (req, res, next) => {
const { title, content } = req.body;
try {
if (!title || !content) {
throw new Error('제목과 내용을 입력해 주세요');
}
// 게시글 생성
const post = await Post.create({
title,
content,
});
res.redirect(`/posts/${post.shortId}`);
} catch (err) {
next(err);
}
});
router.post('/:shortId', async (req, res, next) => {
const { shortId } = req.params;
const { title, content } = req.body;
try {
if (!title || !content) {
throw new Error('제목과 내용을 입력해 주세요');
}
// shortId 로 게시글 수정
await Post.update({shortId}, {
title, content
});
res.redirect(`/posts/${shortId}`);
} catch (err) {
next(err);
}
});
router.delete('/:shortId', async (req, res, next) => {
const { shortId } = req.params;
// shortId 로 게시글 삭제
await Post.deleteOne({shortId});
res.send('OK');
});
utils/async-handlers
module.exports = (requestHandler) => {
return async (req, res, next) => {
try {
await requestHandler(req, res);
} catch(e) {
next(e);
}
}
}
routes/posts.js
router.get('/', asyncHandler (async (req, res) => {
const posts = await Post.find({});
res.render('post/list', { posts });
}));
request handler를 asyncHandler 안에 넣어 그 안에서 try catch로 에러를 거른다음 진행하는것이다.
이렇게하면 라우팅에서 에러를 잡을 필요가 없다.
router.get('/', asyncHandler(async (req, res) => {
if (req.query.write) {
res.render('post/edit');
return;
}
// url 쿼리에서 page 받기, 기본값 1
const page = Number(req.query.page || 1);
// url 쿼리에서 perPage 받기, 기본값 10
const perPage = Number(req.query.perPage || 10);
// 전체 게시글 수 쿼리하기
// total, posts 를 Promise.all 을 사용해 동시에 호출하기
const [total, posts] = await Promise.all([
Post.countDocuments({}),
Post
.find({})
.sort({createdAt: -1})
.skip(perPage * (page - 1))
.limit(perPage)
]);
const totalPage = Math.ceil(total / perPage);
res.render('post/list', { posts, page, perPage, totalPage });
}));
이 코드는 쿼리로 한페이지에 표시되는 게시글 개수와 페이지넘버를 받고있어서 쿼리에서 불러오는데,
처음 접속하면 1페이지인데 그때는 쿼리값이 없으므로 디폴트값을 지정해준다.
sort는 생성일자를 역순으로 정렬, skip은 perPage만큼의 게시글 개수를 skip하고 표시, limit는 perPage만큼의개수만 표시 이다.
total과 posts는 각각 독립적으로 작동하는것이라서 promise.all을 사용한다