[TIL] Node 숙련 (2) 23.06.20

이상훈·2023년 6월 21일
0

[내일배움캠프]

목록 보기
31/68

✔️오늘 한일!

  • Node.js 숙련 강의 수강완료
  • 회원가입 기능 구현
  • 로그인 기능 구현
  • middleware를 구성하여 회원가입 후 로그인 했을때만 게시글 작성,수정,삭제 기능 구현

과제를 하던 도중 게시글 전체조회 시 출력해주는 내용 중에 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"
  }
}
profile
코린이

0개의 댓글