ํ”„๋กœ์ ํŠธ

[react-query] ์ข‹์•„์š” ๊ธฐ๋Šฅ ์ตœ์ ํ™”ํ•˜๊ธฐ

Yuuuki 2024. 7. 2. 11:03

์ข‹์•„์š”๋Š” ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋Š”๊ฒƒ์ด ๋” ํšจ์œจ์ ์ด๋ผ๊ณ  ํŒ๋‹จํ•˜์—ฌ ์ด์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์˜€๋‹ค.

 

๊ฒŒ์‹œ๊ธ€๊ณผ ๋Œ“๊ธ€, ๋Œ€๋Œ“๊ธ€์— ์ข‹์•„์š”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ๊ณ , ์ข‹์•„์š”์— ๋Œ€ํ•œ collection ๋˜ํ•œ ๋ถ„๋ฆฌํ•ด๋‘๊ณ , post์™€ comment๋Š” likeCount ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ, ์ข‹์•„์š”๊ฐ€ ๋ณ€๊ฒฝ๋ ๋•Œ๋งˆ๋‹ค ์ฟผ๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š๋„๋ก ํ•˜์˜€๋‹ค.

 

 

๐Ÿ“Ž DB collection ์ฐธ๊ณ 

https://s-organization-335.gitbook.io/meongnang

 

Firebase DB ์„ค๊ณ„ | ์„ฑ๋Šฅ ์ตœ์ ํ™” & ๊ธฐ์ˆ ์  ์˜์‚ฌ๊ฒฐ์ •

๐Ÿ‘ค User Users FieldType ใ„ด Following FieldType ใ„ด Follower FieldType Follow ์ •๋ณด๋ฅผ User ํ…Œ์ด๋ธ”์—์„œ ํ•œ๋ฒˆ์— ๊ด€๋ฆฌํ•˜๋Š”๊ฒƒ๋ณด๋‹ค, M:N ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์œ ์ €์˜ ํ•˜์œ„ ํ…Œ์ด๋ธ”๋กœ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜์˜€๋‹ค. /users/myUserId/

s-organization-335.gitbook.io

 

Optimistic update

Optimistic update๋Š” ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž์—๊ฒŒ ๋จผ์ € ๋ณ€๊ฒฝ๋œ ๋‚ด์šฉ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ์ˆ ๋กœ ์‚ฌ์šฉ์ž ui์—์„œ ์ฆ‰์‹œ ์‘๋‹ต์„๋ณด์—ฌ์ฃผ๊ณ  ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ์ „์†กํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋น ๋ฅธ ์‘๋‹ต์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๐Ÿ‘‰๐Ÿป ๋งŽ์€ interaction์ด ๋ฐœ์ƒํ•˜๋Š” ์ข‹์•„์š” ๊ธฐ๋Šฅ์— optimistic update๋ฅผ ์ ์šฉ

๐Ÿ‘‰๐Ÿป ์ด์ „๋ณด๋‹ค ๋น ๋ฅธ ์‘๋‹ต ์†๋„๋กœ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ค‘๋ณต๋˜๋Š” ๊ฐ™์€ ์•ก์…˜์„ ์—ฌ๋Ÿฌ๋ฒˆ ์‹œ๋„ํ•˜์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ๋“ค์„ ๊ฐ€์งˆ์ˆ˜ ์žˆ๋‹ค.

 

 

export const useCreatePostLikeReaction = (postId: string, userId: string) => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: () => createPostLikeReaction(postId, userId),
    onMutate: async () => {
      const previousLikeCount = queryClient.getQueryData([
        POST_LIKE_COUNT,
        postId,
      ]);

      queryClient.setQueryData<number | undefined>(
        [POST_LIKE_COUNT, postId],
        (old) => (old ?? 0) + 1
      );

      return { previousLikeCount };
    },
    onError: (_err, _variables, context) => {
      if (context?.previousLikeCount) {
        queryClient.setQueryData(
          [POST_LIKE_COUNT, postId],
          context.previousLikeCount
        );
      }
    },
    onSettled: () => {
      queryClient.invalidateQueries({
        queryKey: [POST_LIKE_STATUS, postId, userId],
      });
      queryClient.invalidateQueries({ queryKey: [POST_LIKE_COUNT, postId] });
      queryClient.invalidateQueries({ queryKey: [POST_LIKED_BY_USER, userId] });
    },
  });
};

 

 

โ—๏ธ๋ฌธ์ œ์ 
๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง ๋ฐœ์ƒ ๋ฌธ์ œ
 

๋ฉ”์ธํŽ˜์ด์ง€(์ „์ฒด ๊ฒŒ์‹œ๊ธ€ ํ™•์ธ๊ฐ€๋Šฅ)์—์„œ๋„, ์ข‹์•„์š”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋‹ค๋ณด๋‹ˆ, ๋ฉ”์ธ์—์„œ ์ „์ฒด postCard๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌํ‚ค๋Š” [POST]๋กœ ์ง€์ •๋˜์–ด์žˆ๊ณ , ๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ, ๋ฉ”์ธํŽ˜์ด์ง€์—์„œ ์ข‹์•„์š” ํ† ๊ธ€์„ ํ• ๋•Œ post ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์„œ likeCount๋ฅผ ์–ป์œผ๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, ์ƒ์„ธํŽ˜์ด์ง€์—์„œ๋Š” [Post,PostId]๋งŒ invalidateํ•ด๋„๋˜์ง€๋งŒ, ๋ฉ”์ธํŽ˜์ด์ง€์—์„œ ์ข‹์•„์š” ํ† ๊ธ€์„ ํ†ตํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•ด์„  [POST] invalidateํ•˜๋‹ค๋ณด๋‹ˆ, ์ข‹์•„์š” ํ† ๊ธ€ํ• ๋•Œ๋งˆ๋‹ค ์Šคํฌ๋กคํ•œ ์˜์—ญ๊นŒ์ง€ ๋ชจ๋“  postCard๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•œ๋‹ค….

 

 

โœจ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

 

๐Ÿ‘‰๐Ÿป likeCount API ๋ถ„๋ฆฌ

postData์˜ likeCount๋ฅผ LikeToggleButton์— props๋ฅผ ๋‚ด๋ ค์ฃผ๋Š” ๋ฐฉ์‹์ด ์•„๋‹Œ post์˜ likeCountํ•„๋“œ๊ฐ’์„ ์–ป์–ด์˜ค๋Š” getPostLikeCount๋ฅผ ๋ถ„๋ฆฌํ•ด์ฃผ์—ˆ๋‹ค.

 
export const getPostLikeCount = async (postId: string) => {
  const postRef = doc(db, "posts", postId);
  const docSnap = await getDoc(postRef);
  if (docSnap.exists()) {
    const postData = docSnap.data() as postDto;
    return postData.likeCount;
  } else {
    throw new Error("ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
  }
};

 

๐Ÿ‘‰๐Ÿป ์ข‹์•„์š” ๋ฒ„ํŠผ๋งŒ ๋ฆฌ๋ Œ๋”๋ง ๋ฐœ์ƒ