인피니트 스크롤링 (완성)

저번시간에 lastId방식을 완성시키지 않았었습니다.

lastId는 다음과 같이 구현해 줄 것입니다.

  • 프론트에서 마지막 메인포스트의 아이디데이터를 백앤드서버로 보내준다.

  • 백앤드 서버에서는 그보다 아이디가 작은 10개를 보내준다.

  • 34개의 글이있다면 마지막에는 4개의 데이터만 올것이다.

  • 만약 10개의 데이터가 왔다면 hasmorePosts를 true로 아니면 false로해서 더이상 로드를 막는다.

일단 useEffect안에서 lastId를 정해줄 것입니다.

  useEffect(() => {
    function onScroll() {
      if (
        window.pageYOffset + document.documentElement.clientHeight >
        document.documentElement.scrollHeight - 300
      ) {
        if (hasMorePost && !loadPostsLoading) {
          const lastId = mainPosts[mainPosts.length - 1]?.id;
          dispatch({ type: LOAD_POSTS_REQUEST, lastId });
        }
      }
    }
    window.addEventListener("scroll", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      //리턴해서 다시 삭제 안해주면 메모리에 쌓이게 된다.
    };
  }, [hasMorePost, loadPostsLoading, mainPosts]);
const lastId = mainPosts[mainPosts.length - 1]?.id;
//mainPost가 처음에는 없기때문에 ? 안전장치

리듀서함수에는 다음 내용으로 바꿔주고

draft.mainPosts = draft.mainPosts.concat(action.data); //앞에 추가해야 게시글이 위에 나타난다.
draft.hasMorePost = action.data.length === 10;

saga에서 서버로 요청을 보낼때 다음과 같이 해줍니다.

async function loadPostAPI(lastId) {
  //data가 undifined인 경우 0
  const response = await axios.get(`/posts?lastId=${lastId || 0}`); //queryString (data 캐싱도 할 수 있다.)
  return response.data;
}

처음에 요청을 보낼때는 data가 undifined이기 때문에 0을 넣어줬습니다.

이제 라우터로 넘어가게 되면

일단 LastId방식을 사용하기 위해서는 Op라는 Sequelize매소드가 필요합니다.

const { Op } = require("sequelize"); //오피
router.get("/", async (req, res, next) => {
  try {
    const where = {};
    if (parseInt(req.query.lastId, 10)) {
      //초기 로딩이 아닐경우 이부분(초기로딩이면 0) lastId보다 작은걸 불러와라
      where.id = { [Op.lt]: parseInt(req.query.lastId, 10) }; //보다 작은걸 불러오면 된다.
    }
    //DB여러개 가져올때
    const posts = await Post.findAll({
      where, //위에서 작성한 조건 추가
      limit: 10, //10개만 가져와라
      order: [
        ["createdAt", "DESC"], //게시글늦게 생성된 순서로
        [Comment, "createdAt", "DESC"], //댓글늦게 생성된 순서로
      ],

      include: [
        { model: User, attributes: ["id", "nickname"] }, //작성자
        { model: User, as: "Likers", attributes: ["id"] }, //좋아요 누른사람
        { model: Image },
        {
          model: Comment, //댓글작성자를 다시
          include: [{ model: User, attributes: ["id", "nickname"] }],
        },
        {
          //리트윗 게시글 포함하도록
          model: Post,
          as: "Retweet",
          include: [
            { model: User, attributes: ["id", "nickname"] },
            { model: Image },
          ],
        },
      ],
    });
    res.status(200).json(posts);
  } catch (e) {
    console.error(e);
    next(e);
  }
});

자 이것으로, 백앤드 서버가 완성되었습니다!!!!

다음부터는 next.js를 활용한 SSR (서버사이드 렌더링을 해보겠습니다)

Last updated