헬롤' s Blog

[React] 플리커링 현상 해결하기

개발을 거의 다 마친 상황..에서 마주한 한가지 문제

거슬리는 부분을 찾아냈다. 바로 플리커링(flickering) 현상이다.

⭐️ 왜 일어나고 있는 것인가?

원인은 이렇다.

일단 이 프로젝트는 suspense로 부모 컴포넌트가 싸여있고 빈 div를 fallback으로 두고 있다.

{
  path: PATH.PLANNING,
  element: (
    <Suspense fallback={<div></div>}>
      <Lazy.PlanningPage />
     </Suspense>
  ),
 },

열리는 모달에는 댓글들을 불러오는 api가 모달이 열려질때 불려진다. 이 댓글을 불러오는 api가 완료되길 기다리는 동안

Suspense에서 설정해놓은 Callback인 빈 div 화면이 전체에 걸쳐서 플리커링 현상을 일으키는 것이다.

👍 해결책

1. Suspense를 CommentField에 씌워준다.

// ScheduleModal 컴포넌트
// ...
 
      <Suspense fallback={<div>Loading...</div>}>
        <CommentField boardId={schedule.boardId} />
      </Suspense>

Suspense가 중첩된다면 가장 가까이에 있는 Suspense가 적용되는 것을 이용하는 것이다.

CommentField에서 comment들을 불러오고 있는 CommentField를 Suspense가 덮어 씌어준다면 플리커링 현상은 일어나지 않고 댓글 목록에서만 로딩이 일어날 것이다.

🔥 또 다른 해결책?

2. prefetch를 해준다

prefetch란? 사용자가 가까운 미래에 탐색할 가능성이 '있는' 페이지에 대해 백그라운드에서 리소스를 추론적으로 가져오는 방식 이렇게 하면 사용자가 해당 페이지로 이동하기로 선택한 경우 미리 가져온 페이지의 로드 시간을 크게 줄일 수 있다. prefetch를 통해서 data를 미리 불러와 준다면 Suspense가 동작하지 않고 플리커링 현상을 해결할 수 있다.

  // 현재 달력의 일정의 댓글을 prefetch 해준다.
  data?.result.scheduleList.forEach((schedule) => {
      prefetchScheduleComment(schedule.boardId);
    });

🔥 결국 선택한 해결책은?

이 해결책중 선택한 해결책은 Suspense를 다시 쓰는 것이다. 일정이 많아졌을때는 생각 보다 어쩌면 필요없을 수도 있는 많은 수의 api 요청이 있었다. 또한 댓글을 불러오는 것은 비교적 간단한 get요청이기에 suspense를 써서 플리커링 현상을 막기로 결정했다.

😀 만약 이렇게 한다면? (UX)

일정에 마우스를 hover할때 댓글을 가져오는 요청을 보내는 것이다. 일정 상세보기 및 댓글을 봐야한다면 결국 일정에 마우스를 가져다 댈수 밖에 없는데 이렇게 한다면 사용자는 로딩 없는 더욱 빠른 화면을 볼 수 있고 또한 불필요한 api요청을 없앨 수도 있을 것 같다.