본문 바로가기

🌼 TIL

유저 랭킹기능 구현 - Next.js, Firebase, reactQuery

구현할 기능

게시물 갯수, 팔로워 수, 댓글 수 별 유저 랭킹 기능

구현 이유

50명의 유저에게 피드백 받은 후 게시물 게시 유도를 위한 추가기능 구현

참고 회의 내용 : https://www.notion.so/e7ae5984cf72445a8f9dff0042e7480c?v=035c9f9341a243668c11c1f213969cb5&pvs=4 

 

The all-in-one workspace for your notes, tasks, wikis, and databases - Notion

A new tool for teams & individuals that blends everyday work apps into one.

www.notion.so

기능 구현

reactQuery를 활용하여 데이터를 요청한다.

여기서 게시물, 팔로워, 댓글에 따라 각기 다른 요청방법을 사용한다.

- 전체 데이터를 불러온 후 현재 로그인 된 유저 기준 랭킹 번호를 알아낸다
- 필요한 데이터를 filter와 map을 통해 구한다
- slice를 통해 유저 기준 앞,뒤 유저 데이터를 구한다

 

게시물 랭킹

const { data: rankPost } = useQuery(['rankPost'], getData, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });
  // 모든 유저 데이터 가져오기
  const { data: rankUser } = useQuery(['rankUser'], getUser, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });

  // 유저 목록 추출
  const users: string[] = Array.from(
    new Set(rankPost?.map((post: RankPost) => post.creator))
  );

  // 유저별 포스트 추출
  let userPosts: RankUserPost[] = users.reduce<RankUserPost[]>((acc, user) => {
    acc.push({
      user,
      posts: rankPost.filter((post: RankPost) => post.creator === user),
    });
    return acc;
  }, []);

  // 유저별 포스트 정렬
  userPosts.sort(function (a, b) {
    if (a.posts.length < b.posts.length) {
      return 1;
    }
    if (a.posts.length > b.posts.length) {
      return -1;
    }
    return 0;
  });

  //해당 유저의 랭킹
  const myRankNum = userPosts?.map((item: any, index: any) => {
    if (item.user === authService.currentUser?.uid) return index;
  });
  const myRanking: any = myRankNum?.filter((item: any) => item > -1);
  const myRank = userPosts?.filter((item: any) => {
    if (item.user === authService.currentUser?.uid) {
      return item;
    }
  });
  // 해당 유저 기준 앞 뒤 랭킹 데이터
  const preRank = userPosts?.slice(myRanking - 1, myRanking);
  const nextRank = userPosts?.slice(myRanking, myRanking + 1);
  const nextRankNum = nextRank?.filter((item: any, index: any) => index === 1);

팔로워 랭킹

// 팔로워 데이터 불러오기
  const { data: rankFollower } = useQuery(['rankFollwer'], getFollow, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });

  // 팔로워 랭킹 길이에 따른 정렬하기
  const rankFollowerData = rankFollower?.sort((a: any, b: any) => {
    if (a.follow.length < b.follow.length) {
      return 1;
    } else if (a.follow.length > b.follow.length) {
      return -1;
    } else {
      return 0;
    }
  });

  // 해당 유저 랭킹 번호 index로 나열하여 알아내기
  const myRankNum = rankFollowerData?.map((item: any, index: any) => {
    if (item.docId === authService.currentUser?.uid) return index;
  });
  const myRanking: any = myRankNum?.filter((item: any) => item > -1);
  const myRank = rankFollower?.filter((item: any) => {
    if (item.docId === authService.currentUser?.uid) {
      return item;
    }
  });
  //해당 유저 기준 앞,뒤 랭킹 데이터
  const preRank = rankFollower?.slice(myRanking - 1, myRanking);
  const nextRank = rankFollower?.slice(myRanking, myRanking + 1);
  const nextRankNum = nextRank?.filter((item: any, index: any) => index === 1);
  const { data: rankUser } = useQuery(['rankUser'], getUser, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });

댓글 랭킹

// 모든 포스트 데이터 가져오기
  const { data: rankPost } = useQuery(['rankPost'], getData, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });
  // 모든 유저 데이터 가져오기
  const { data: rankUser } = useQuery(['rankUser'], getUser, {
    staleTime: 1000 * 60 * 10,
    cacheTime: 1000 * 60 * 15,
  });
  // 댓글 데이터 추출
  const getCommentData = async () => {
    const results = await Promise.all(
      rankPost.map((item: any) =>
        getComment({ queryKey: ['getCommentData', item.id] })
      )
    );

    const commentsData = results
      .filter((result: any) => result.length > 0)
      .reduce((acc: any, cur: any) => {
        return [...acc, ...cur];
      }, []);

    setCommentsDataList(commentsData);
  };

  // 유저 목록 추출
  const users: string[] = Array.from(
    new Set(rankPost?.map((post: RankPost) => post.creator))
  );

  // 유저별 포스트 추출
  let userComments: RankUserPost[] = users.reduce<RankUserPost[]>(
    (acc, user) => {
      acc.push({
        user,
        posts: commentsDataList.filter(
          (post: RankPost) => post.creatorUid === user
        ),
      });
      return acc;
    },
    []
  );

  // 유저별 포스트 정렬
  userComments.sort(function (a, b) {
    if (a.posts.length < b.posts.length) {
      return 1;
    }
    if (a.posts.length > b.posts.length) {
      return -1;
    }
    return 0;
  });
// 해당 유저 랭킹 데이터 호출
  const myRankNum = userComments?.map((item: any, index: any) => {
    if (item.user === authService.currentUser?.uid) return index;
  });
  const myRanking: any = myRankNum?.filter((item: any) => item > -1);
  const myRank = userComments?.filter((item: any) => {
    if (item.user === authService.currentUser?.uid) {
      return item;
    }
  });
// 해당 유저 기준 앞,뒤 랭킹 데이터
  const preRank = userComments?.slice(myRanking - 1, myRanking);
  const nextRank = userComments?.slice(myRanking, myRanking + 1);
  const nextRankNum = nextRank?.filter((item: any, index: any) => index === 1);

 

 

결과