🔗 마이페이지(1)

 

[팀프로젝트] 리액트로 뉴스피드 웹사이트 제작하기 - 마이페이지(1)

🔗 사전기획 [팀프로젝트] 리액트로 뉴스피드 웹사이트 제작하기 - 사전기획리액트로 첫 팀프로젝트가 시작됐다. 뭔가 프로젝트다운 프로젝트를 하는 것 같다. 인스타그램이나 페이스북,  블

ejunyang.tistory.com

 

 

 

 

 

✏️ 내가 쓴 게시글 불러오기

로그인한 아이디와 같은 유저 아이디를 가진 데이터의 모든 정보를 posts 테이블에서 가져온다.

 const { data: postData, error: postError } = await supabase
        .from('posts')
        .select('*')
        .eq('user_id', userData.email);
      setPosts(postData);

      if (postError) {
        console.error('게시글 정보를 가져오지 못했습니다.', postError);
        return;
      }

 

 

❤️ 좋아요 누른 게시글 불러오기

    const { data: likeData, error: likeError } = await supabase
        .from('user_info')
        .select('post_heart')
        .eq('user_id', userData.email);

      if (likeError) {
        console.error('좋아요한 게시글 정보를 가져오지 못했습니다.', likeError);
        return;
      }

 

JSON 형식의 문자열로 저장된 게시글 ID들이 들어있고, 이 문자열을 JSON.parse를 사용하여 JavaScript 배열로 변환한 다음 likedPostIds라는 변수에 저장한다.

 

let likedPostIds = JSON.parse(likeData[0].post_heart);

 

좋아요한 게시글 ID가 담겨있는 likedPostId를 map 을 돌려 새로운 배열을 반환한다. 각 게시물 ID (postId)에 대해 Supabase 데이터베이스에서 해당 ID와 일치하는 게시물의 세부 데이터를 가져온다. likedPostDetails 배열에서 null이 아닌 요소들만 필터링하여 setLikedPosts 함수로 전달한다.

      try {
        const likedPostDetails = await likedPostIds.map(async (postId) => {
            const { data: likedPostData, error } = await supabase
            .from('posts')
            .select('*')
            .eq('id', postId);

            if (error) {
              console.error('좋아요한 게시글의 상세 정보를 가져오지 못했습니다.', error);
              return null;
            }
            return likedPostData;
          })
        setLikedPosts(likedPostDetails.filter((post) => post !== null));
      } catch (error) {
        console.error('오류', error);
      }

2

 

👾 오류

likedPostIds가 배열이 아니라는 타입오류가 났다. 찾아보니 async 함수는 항상 Promise를 반환한다는 것을 알아냈다. 반환된 프로미스 객체를 비동기식으로 처리하기 위래 Promise all 메서드를 사용해보았다.

 

🔗 참고자료

 

Promise.all() 로 비동기 처리를 구현해 보자

- Promise.all() 은 여러 개의 Promise 들을 비동기적으로 실행하여 처리할 수 있다.

velog.io

 

 

 

💡 해결

흐름은 아래와 같다. 아래 흐름으로 간다면 Promise.all이 완료됐을 때, likedPostDetails는 각 postId에 대한 쿼리 결과의 배열이 된다.

  • Promise.all은 전달된 모든 Promise가 해결될 때까지 기다린 후, 그 결과를 배열로 반환
  • likedPostIds.map은 각 postId에 대해 비동기 작업을 수행하는 Promise 객체의 배열을 반환
  • 해당 배열을 Promise.all에 전달하여 모든 비동기 작업이 완료될 때까지 기다림
  • await를 사용하여 모든 Promise가 완료될 때까지 기다림

 

 const likedPostDetails = await Promise.all(
          likedPostIds.map(async (postId) => {
            const { data: likedPostData, error } = await supabase.from('posts').select('*').eq('id', postId);

            if (error) {
              console.error('좋아요한 게시글의 상세 정보를 가져오지 못했습니다.', error);
              return null;
            }
            return likedPostData;
          })
        );
        setLikedPosts(likedPostDetails.filter((post) => post !== null));
      } catch (error) {
        console.error('오류', error);
      }

 

 

 

📌 북마크한 게시글 불러오기

 const { data: saveData, error: saveError } = await supabase
        .from('user_info')
        .select('post_save')
        .eq('user_id', userData.email);
      setSavePosts(saveData);

      if (saveError) {
        console.error('북마크한 게시글 정보를 가져오지 못했습니다.', saveError);
        return;
      }

 

 

saveData[0]가 존재하는지 확인하고, 존재하지 않으면 undefined 처리. 옵셔널 체이닝으로(?) saveData[0]가 존재하지 않으면 undefined를 반환한다. 좋아요 게시글의 세부데이터를 가져오는 방식과 같은 방식이다.

 

let savePostIds = JSON.parse(saveData[0]?.post_save || '[]');
      try {
        const savePostDetails = await Promise.all(
          savePostIds.map(async (postId) => {
            const { data: savedPostData, error } = await supabase.from('posts').select('*').eq('id', postId);

            if (error) {
              console.error('북마크한 게시글의 상세 정보를 가져오지 못했습니다.', error);
              return null;
            }
            return savedPostData;
          })
        );
        setSavePosts(savePostDetails.filter((post) => post !== null));
      } catch (error) {
        console.error('오류', error);
      }
    };

+ Recent posts