과제를 하던 도중 게시글 전체조회 시 출력해주는 내용 중에 user schema에 있는 nickname을 출력해주는 과정에서 문제가 생겼다.
기존 코드
// 게시글 전체조회
router.get("/posts", async (req, res) => {
const showPost = await Posts.find({}).sort({ createdAt: -1 });
if (!showPost.length) {
return res.status(404).json({ message: "게시글이 없습니다." });
}
const data = showPost.map((post) => {
return {
postId: post._id,
user: post.user,
title: post.title,
createdAt: post.createdAt,
};
});
res.json({
showPost: data,
});
});
post schema에 nickname이 없어 기존 처럼 post.nickname으로 출력과정을 처리해줄 수가 없어 mongoose를 구글링해보니 populate라는게 있어 자료를 참고해보며 작성해봤다.
// 게시글 전체조회
router.get("/posts", async (req, res) => {
const showPost = await Posts.find({}).sort({ createdAt: -1 });.populate("userId")
if (!showPost.length) {
return res.status(404).json({ message: "게시글이 없습니다." });
}
const data = showPost.map(async (post) => {
const user = await User.findById(post.userId)
return {
title: post.title,
nickname: userId,
content : post.content
createdAt: post.createdAt,
};
});
res.json({
showPost: data,
});
});
비동기 처리를 위해 async/await
을 사용하여 서버를 가동 후 실행해 보았으나 결과를 출력해주지 않고 promise배열만 리턴해주었다.
이것저것 수정하면서 시도해봐도 promise배열을 리턴해주거나 type error가 발생해서 map함수의 비동기처리에 대해 찾아보니 map()
메서드는 동기적으로 작동하기 때문에 async
함수 내에서 await
를 사용할 수 없다는걸 알았다.
map()
메서드를 사용하여 비동기 작업을 수행해야 한다면 Promise.all()
과 같은 비동기 제어 흐름 메서드를 사용하여 비동기 작업을 처리해야 한다.
Prmoise.all(iterable)
iterable
내의 모든 프로미스가 이행한 뒤 이행하고, 어떤 프로미스가 거부하면 즉시 거부하는 프로미스를 반환합니다. 반환된 프로미스가 이행하는 경우iterable
내의 프로미스가 결정한 값을 모은 배열이 이행 값입니다. 반환된 프로미스가 거부하는 경우iterable
내의 거부한 프로미스의 이유를 그대로 사용합니다. 이 메서드는 여러 프로미스의 결과를 모을 때 유용합니다.
// 게시글 전체조회
router.get("/posts", async (req, res) => {
const showPost = await Posts.find({}).sort({ createdAt: -1 }).populate("userId");
if (!showPost.length) {
return res.status(404).json({ message: "게시글이 없습니다." });
}
const data = await Promise.all(
showPost.map(async (post) => {
const user = await Users.findById(post.userId);
return {
title: post.title,
nickname: user ? user.nickname : "",
createdAt: post.createdAt,
};
})
);
res.json({
showPost: data,
});
});
showPost.map()
메서드 내부에서 각각의 'post'에 대해 비동기 작업을 수행하고, User.findById()
메서드를 await
하여 사용자 정보를 가져온다. 이후 Promise.all()
을 사용하여 병렬로 여러 개의 비동기 작업을 처리하고 완료될 때까지 기다린 다음 결과를 반환하게 코드를 작성하였다.
출력결과
{
"Detail": {
"title": "test1",
"nickname": "테스트계정1",
"content": "test1",
"createdAt": "2023-06-20T12:36:31.447Z"
}
}