본문 바로가기

공부/트러블 슈팅

[트러블 슈팅] 방콕 스타일 (새로고침 시 좋아요 랜덤 활성화 이슈)

반응형

 

팀 프로젝트 방콕스타일을 진행하면서 발생한 트러블 슈팅입니다.

발생한 오류 🔥

방콕 스타일 뉴스피드 프로젝트에서 게시물 목록을 렌더링 하던 중 페이지를 새로고침했을 때, `좋아요`가 랜덤으로 활성화된 상태로 표시되는 오류가 발생했습니다.

 

좋아요가 랜덤으로 표시되는 건 아주 큰 문제였기 때문에 해결이 시급했습니다. 

 

해결 과정 🔎

useOnAuthStateChange

 

supabase에서 auth 관련 event가 발생할 때마다 알림을 받는 메서드입니다. 그래서 session이 있으면 컨텍스트에 `session.user`정보를 보내서 컨텍스트에서 유저 정보를 저장하게 됩니다.

// 유저정보를 context에 저장하는 함수
const useOnAuthStateChange = () => {
  const { signIn } = useContext(EntireContext);
  useEffect(() => {
    const { data: authListener } = supabase.auth.onAuthStateChange((_, session) => {
      session && signIn(session.user);
    });

    return () => {
      authListener.subscription.unsubscribe();
    };
  }, []);
};

export default useOnAuthStateChange;

 

 

컨텍스트의 `userInfo`유저 정보가 있다면 유저 ID를 가져와 `getAllData`메서드에 전달하는 방식으로 로직을 짰습니다.

  const { setDisplayedPosts, setAllPosts, userInfo } = useContext(EntireContext);
  const [loading, setLoading] = useState(false);
  // 유저 정보 확인
  const userId = !!userInfo ? userInfo.id : null;

  const fetchPosts = useCallback(async () => {
    try {
      setLoading(true);
      const response = await getAllData(userId);
      const data = formattedLikeData(response);

      // 전체 게시글 데이터 저장
      setAllPosts(data);

      // 실제 화면에 보여줄 데이터 저장
      setDisplayedPosts(filteredDisplayedPostsData(LIMIT_NUMBER, data));
    } catch (error) {
      console.error("게시글 데이터를 가져오지 못했습니다.", error);
    } finally {
      setLoading(false);
    }
  }, [userId]);

  useEffect(() => {
    fetchPosts();
  }, [fetchPosts]);

 

근데 ` useOnAuthStateChange`비동기로 동작하기 때문에 로그인 여부에 따라 유저 정보를 컨텍스트에 업데이트하는 시간이 소요되는 문제가 있어서 `userInfo`가 설정되기 전에 `fetchPosts`함수가 먼저 실행 돼 `userInfo`가 null인 상태로 데이터를 가져오는 것이었습니다. 

 

오류 가설

 

1. `useOnAuthStateChange` 훅의 비동기 동작으로 `userInfo`가 업데이트되기 전 `fetchPosts`함수가 호출됨.

 

이를 해결하기 위해 가장 먼저 시도한 방법은 `useCallback` 의존성 배열에 `userInfo`를 추가하는 것이었습니다.

const fetchPosts = useCallback(async () => {
  if(!userInfo) return;
  try{} catch(err){}
}, [userInfo]);

 

`userInfo`가 업데이트된 후에 다시 fetchPosts가 실행되어, 최신 사용자 정보를 바탕으로 데이터를 가져올 수 있을 것으로 기대했지만 여전히 동일한 문제가 발생했습니다. `userInfo`가 의존성 배열에 포함되었음에도 `useOnAuthStateChange`의 비동기 동작이 여전히 `fetchPosts` 호출 시점에 영향을 미치고 있다는 것이었습니다.

 

결국, `userInfo`가 `null`일 때도 좋아요 정보를 가져오도록 하는 방향으로 문제를 해결해야 된다고 판단했습니다.

해결 방법 ✨

`userInfo`가 `null`이더라도 좋아요 정보를 포함해 데이터를 가져오도록 쿼리를 수정했습니다.

const response = await supabase
  .from("posts")
  .select("*, likes(post_id)")
  .order("created_at", { ascending: false });

 

로그인 여부와 상관없이 모든 게시글의 좋아요 상태를 가져올 수 있도록 하여 `userInfo`와 관계없이 올바르게 표시되었습니다. 결과적으로 페이지를 새로고침해도 좋아요 상태가 유지가 되었습니다.

 

깨달은 점

1. 비동기 로직의 복잡성

비동기 로직이 엮여있는 부분에서는 작은 타이밍 차이로 예기치 않는 오류가 발생할 수 있다는 것을 알게 되었습니다. 이런 오류를 해결하기 위해선 로직의 실행 순서를 정확하게 이해하고, 문제가 발생할 수 있는 경로를 미리 차단해야 한다고 생각했습니다.

 

2. 문제 해결 방법

문제를 해결할 때 하나의 방법에만 집착하기보다는, 다양한 접근 방식을 시도해 보는 것이 중요하다는 걸 알게 되었습니다. 이러한 과정에서 다양한 방법을 테스트해 보고, 그 결과를 분석하는 능력도 중요하다고 느꼈습니다.

 

회고 🧐

이 오류로 이틀을 날렸습니다,,, 이런 경험들이 앞으로 개발할 때 더 나은 판단을 할 수 있게 해 줄 것 같습니다.

 

아직 많이 부족합니다. 조언은 언제나 환영입니다~!

반응형